Where have you found it useful to re-bless or re-construct* an object?
I anticipate two scenario types:An explanation of what useful purpose is served, or what this transformation represents, would also be insightful. Thanks!
"One is enough. If you are acquainted with the principle, what do you care for the myriad instances and applications?"
- Henry David Thoreau, Walden
Re-blessing doesn't do #2.
It would be a good point to disentangle blessing from object construction. I'll remove that ambiguity from my question by specifying that I am also interested in re-construction.
"One is enough. If you are acquainted with the principle, what do you care for the myriad instances and applications?"
- Henry David Thoreau, Walden
-- Randal L. Schwartz, Perl hacker
Be sure to read my standard disclaimer if this is a reply.
"One is enough. If you are acquainted with the principle, what do you care for the myriad instances and applications?"
- Henry David Thoreau, Walden
But what if the the classes are intentionally written and maintained with this in mind? Users don't even need to peek inside when the action is supported through methods. Maintaining sibling subclasses that rely on the same parent doesn't seem abusive or even unusual.
An example of my own use is dealing with user instances. Prior to validation, users interact with the system via an instance of the anon_user class. Should they log in, their instance is elevated into one of the user classes (depending on their status). The effects of some methods will change, and additional data might get grafted on. But I also want all the information I've already collected when I go to create their validated user object, and lo, there it is behind the anon_user veil, ready and waiting. Sometimes they go through a cascade of changes in user-type. What would be the object-appropriate way for me to go from one state to the next in such a situation?
I can agree with you that it doesn't make sense to grab a random data structure ("how it's implemented") and start abusing it. The author should have the freedom to make any changes they want under the hood. But when you are the author, such preservation and re-use of data structures seems prudent if applicable.
"One is enough. If you are acquainted with the principle, what do you care for the myriad instances and applications?"
- Henry David Thoreau, Walden
The reblessing you want to do is really changing the authobj. So, just change the authobj! There's no need to get all fancy. In fact, a good rule of thumb is "If I have to ask if something is possible on Perlmonks, I probably should rethink my design." About 90% of the time I ask a question, my design changes. This is a good thing.
This sounds like compartmentalizing the aspects that might vary (method results) into a seperate object (authobj). Then, if you need to change how something works, you swap out the authobj for another one.
That sounds like more work to me, and for what? The method variations still have their own spaces, seperate by class lines, but you're suggesting using multiple objects where I only need one. If I needed authobjects for other types of objects I could see that being a compelling argument (design the piece, then plug in where needed). But it seems like a smaller change to start using a different name (rebless) for an object than to throw away part of it, create a new part, and plug it into the hole.
For clarification of my motivation, I'm not asking if this IS possible (I know it is, conceptually and in practice) but why ELSE it might be desirable (or undesirable.) I'm certainly not afraid to change my ways- if I was I wouldn't be re-implementing my current project with OO code after months of development. I'm also open to accepting I am misguided- but it takes a clear argument tthat puts me back on course to convince me.
"One is enough. If you are acquainted with the principle, what do you care for the myriad instances and applications?"
- Henry David Thoreau, Walden
What does this mean? Well, under your proposed system, it means that by fixing a bug in how User::Superman behaves, you might have changed the behavior of User::Anonymous. I'm pretty sure you would agree that this is undesirable.
The solution is to isolate the part that changes. Every user needs a set of authorizations, but that set (as a whole!) will change. So, isolate (or encapsulate) the bit that changes.
It is a tiny bit more upfront work. Yet, you will discover that you have more capabilities to the system than if you gone with your system. It's a bit of a leap of faith, but I hope you will trust me and be willing to make it, for your sake.
This does seem to be sound advice, and I appreciate everyone for pointing it out. I think the key is recognizing what level of compartmentalization is appropriate for a particular situation.
Public object methods are a widely recognized contract that, without warning well in advance, the effects of calling a method will not change. The safety of compartmentalizing comes from that contract alone, not the form of the compartment. If I take any space and give it the same contract, it becomes a compartment of just such strength. By doing so you make available compartments of different shapes and sizes, from a simple scalar to the most complicated data structure. The line of delineation is no longer what one might expect- until they read the documentation that details it.
It is the compartmentalization, not how you effect the compartmentalization, that makes it useful. Does it make sense to re-use common, publicly acknowledged contracts to do so? Yes (see Creative Commons). Is it wise to follow that as a guideline unless you have good reason to do otherwise? Sure. But might there be uses that don't follow the guidelines? I believe so. Hence, this entire thread.
"One is enough. If you are acquainted with the principle, what do you care for the myriad instances and applications?"
- Henry David Thoreau, Walden
Have the user object contain an authorization object. Then, when the userobj wants to know if it's allowed to do certain things, it asks the authobj. The authobj replies with a boolean yes-or-no.
But then you have an ugly set of
sub method1 {
...
if ($self->authenticated) {
...
} else {
...
}
...
}
sub method2 {
...
if ($self->authenticated) {
...
} else {
...
}
...
}
sub method3 {
...
if ($self->authenticated) {
...
} else {
...
}
...
}
instead of a nice set of
package User::Anonymous;
sub method1 {
...
}
sub method2 {
...
}
sub method3 {
...
}
package User::Authenticated;
sub method1 {
...
}
sub method2 {
...
}
sub method3 {
...
}
I think checking inside the methods is (security) error prone, and a lot more work, resulting in uglier code that is harder to maintain. Besides that, it's less efficient because of the extra check (which if you abstract properly, is a method call). I prefer doing something that isn't entirely pure in the sense of "how OO was officially meant" (if such a thing even exists) to something that is pure, but causes me and the future maintenance guy extra work. And OO purity is a performance killer in many ways, which is a problem if you happen to work for one of those shops that still care about that.
So you can't easily subclass anymore. Fine with me, because you can still wrap. If I properly designed my User, I'd let you add arbitrary states like Anonymous and Authenticated, and you could change things through that interface. Personally, I don't think inheritance is holy enough to have as a primary design objective. Composition is more useful IMO, and reblessing to change state (combined with inheriting (or mixing in) from a state independent class) is a primitive way of doing that.
Juerd # { site => 'juerd.nl', plp_site => 'plp.juerd.nl', do_not_use => 'spamtrap' }
I am advocating a composition solution in favor of an inheritance solution. Are we just in violent agreement here?
As for not subclassing as easily, it's the reblessing solution that's harder to subclass. Not only am I restricted to a given implemention, but I have to support every single key used by every version of those other implementations. What a nightmare!
Yes. However, I tend to put my authentication code in my cgiapp_prerun and, very rarely, refer to it in other places. This reduces work quite dramatically.
In the case of only authentication, that's a perfect solution. However, sometimes the authentication leads to authorization, and you have a system of user rights scattered all over the place. Instead of having many conditionals, I typically prefer to put all functionality in methods, and indicate rights by (re)blessing into the right package.
it's the reblessing solution that's harder to subclass.
That is what I referred to.
Juerd # { site => 'juerd.nl', plp_site => 'plp.juerd.nl', do_not_use => 'spamtrap' }
I don't see how reblessing is a better solution.
It's nice in terms of security, grouping, maintenance, and more of that. If you really don't see it, then that is too bad; I don't know how I could explain it better than I already have. And I think that you are unable to convince me as much as I am unable to convince you, so I'm going to spend my time on other branches of discussion.
Juerd # { site => 'juerd.nl', plp_site => 'plp.juerd.nl', do_not_use => 'spamtrap' }
Then I'd ask why you wrote this code as OO, since you aren't getting a major benefit of OO: abstraction.
There are many common approaches for doing the kind of thing you describe that don't require breaking encapsulation. They're so common that they have design pattern names, like "decorator" (wrap one object with another), or "strategy" (delegate the handling of certain methods to different objects determined at runtime). You could also just use the original object's public API to get the data to populate the new objects (a "factory" pattern).
Here's a detraction I've missed so far: using classes like this doesn't easily lend itself to more than one volitile layer at a time, and so using internal objects would have an advantage in that respect, as they can be swapped whenever, in any order. Class change seems in line with more fundamental shifts in the nature of the object. At times, perhaps farming out work to a seperate object that you work indirectly with is a little excessive when you can cut out the abstraction layer by designing the classes that fill that space to the same specs. If the classes all rely on the same parent class but represent the differences between objects with the same parent, then switching classes is exactly the sort of abstractive exploit OO is designed to allow. Perhaps my thinking is incorrect, and I welcome correction.
You need to know what type of object to plug into a given role- this doesn't require knowledge of the object's data structure, but does require setting aside a space for that object inside the larger whole and knowing how to interact with it. It needn't know how to interact with the rest of the structure outside it's own space. Any object that you plug in needs to follow the same rules- fit into the same space and allow the same manner of interaction.
You've got to design or find a class that you can assign to manage that space within your greater object, and it has to share methods of interaction with other classes that might fill the same role, and respond in the same way (or you need to put an abstracting layer between the two as glue). So far, this seems like it could be addressed with either an independant object or an additional class layer.
But the class can't safely make assumptions about what is outside it's own space unless you are able and desire to take any extra effort to make it so. Breaking encapsulation, and the pros and cons, is beaten to death elsewhere. But you needn't break encapsulation, if you restrict yourself to that space you know is assigned to you. You just need to allow, or even expect, that you might find data there you didn't create or put there- and maybe that's OK. In fact, maybe it's more than OK.
I recognize the benefit of reading up on patterns. Are these particular patterns all presented in the gang of four book, or can you suggest another?
Then I'd ask why you wrote this code as OO, since you aren't getting a major benefit of OO: abstraction.
Dont you think thats a bit extreme? Simply because you have tight coupling doesnt mean you have sacrificed abstraction. If you can even speak of such a thing in such a way. For instance tight coupling between two classes doesnt mean that you lose any interface abstraction on the objects themselves. If A and B are tightly coupled C need not even know or care about one of them, and treat the other as simply and abstract interface.
I think it really depends on which attributes of OO you think are most important. If you think that inheritance support is the objective then I can see why tight coupling of two classes would bother you. You can't easily subclass[1]. But if you are more concerned with interface abstraction then it makes no difference. And personally ive found that interface abstraction (polymorphism) is much more commonly depended on than inheritance. If you are sane you only subclass things are designed to be subclassable in the first place. Especially in perl.
[1]: This is not strictly true. If both classes defined a sister_class property that returned the other classes name, then the tight coupling could be overriden. If you wanted to subclass either youd have to subclass both. Or you could pass the other classes name back and forth as parameters. This would mean the coupling was a lot weaker. IMO whether it made sense would depend on the circumstances.
If they both support the same interface it makes no difference to you. For instance you are told that you can use methods X and Y and both classes support the method.
Its exactly the same idea when you have something that says "i can use any object that supports a print method to do output". It doesnt care about the class of the object, it cares about the interface of the object.
As for the two classes knowing about each others internals well, thats just life. Do you think there is something wrong with File::Spec because it is tightly coupled to the File::Spec::OSTYPE modules? And do you think that File::Spec somehow presents a loss of abstraction? IMO thats a good example where a set of tightly coupled modules provides a clean abstraction layer.
If I want to make a print_document() method in class Spreadsheet and class WebPage, and sometimes re-bless Spreadsheet into WebPage, that means both classes have to implement print_document() to access the same internal data structures. You can't decide that WebPage would be better off storing things in a tree and Spreadsheet would be better storing them in a HoA, because one might magically become the other at any time, and your methods still have to work.
we're talking about the re-blessed classes themselves. They have no abstraction from each other's internals.
I dont see why thats a given. But having said that, i do agree most likely the two classes would know about each others internals. Otherwise why would you even bother with the reblessing?
If I want to make a print_document() method in class Spreadsheet and class WebPage, and sometimes re-bless Spreadsheet into WebPage, that means both classes have to implement print_document() to access the same internal data structures.
Why is it necessary that they access the same data structures. Prior to rebless the internals structures could be converted? And even if it were necessary, why would it be a problem? Put the code that handles print_document() in one class, then the two classes that play rebless games inherit from that. If print_document itself only uses defined accessors to access its internal state theres no problem.
You can't decide that WebPage would be better off storing things in a tree and Spreadsheet would be better storing them in a HoA, because one might magically become the other at any time, and your methods still have to work.
You make it sound like if you aren't careful you are going to accidentally end up with code that alters it state by reblessing. Obviously you aren't. Its a technique that has specific characteristics which only make sense for certain types of problems. When you are dealing with such problems reblessing is a useful tool. You cant just write something off as a maintenance nightmare simply because the code reblesses itself. If the code has good reasons to do so and is properly documented then it should be no issue.
I gave some examples elsewhere in this thread but to recap: things like delayed instanstiation, caching, object seriliazation ("freezing") are problems where reblessing can represent a reasonable solution.
An example might be you have a graph of nodes that contain data that is expensive to calculate and large to store. You have to traverse the network and perform operations on the objects in some arbitrary sequence which maybe involve you visiting certain nodes much more often than others. Calculating the overall graph is also expensive. You don't have enough memory to store more than a fraction of the objects at one time.
In a situation like this one solution would be to define two classes, one which represents the lite version of a node and one that represents the heavy version. The lite version basically does nothing but turn itself into the heavy version and then redirect the method call (plus some minor infrastructure to handle the LRU cache). The heavy version then has a method that allows it convert itself back to the lite version. Now the code traversing the network doesnt have to know anything about the caching. For all it knows the graph contains only "heavy" objects.
A last comment... I've seen it said that any time you write an 'if' statement you aren't doing OO. If so then I think reblessing represents a clean of way of dealing with an if statement that need be executed only once.
# just for fun ;-)
sub O::v { bless $_[0],'o'; 0 }
sub o::v { bless $_[0],'O'; 1 }
my $o=bless {}, 'o';
print $o->v for 1..10;
Won't there be shared code that accesses internal data? Or code in one class that accesses data set by the other class?
Prior to rebless the internals structures could be converted? And even if it were necessary, why would it be a problem?
What are you gaining by re-blessing then? Sounds like you want to just read the data and make a new object.
Put the code that handles print_document() in one class, then the two classes that play rebless games inherit from that. If print_document itself only uses defined accessors to access its internal state theres no problem.
If these defined accessors are written to work with different internal structures, how can they work on the same data? If someone re-blesses an existing object from one class to the other, they still have to work. All you're doing here is pushing the problem around from one method to another.
Won't there be shared code that accesses internal data? Or code in one class that accesses data set by the other class?
If all accessors are defined in terms of low level operations then all you have to do is overload the low level operations and the highlevel ones are taken care of.
What are you gaining by re-blessing then? Sounds like you want to just read the data and make a new object.
Well if there are many references to a single object then going around and changing them all one by hand is tedius and error prone, and probably not even possible at all. On the other hand reblessing the object affects every reference to the blessed referent so its affect the lot of them in one go. Thats just one gain. Another gain could be what I was referring to in the part of my message you didnt comment on, where the object may have several possible internal representations and the class represents which state the object is in.
If these defined accessors are written to work with different internal structures, how can they work on the same data?
I have to say I dont get what you dont get here. This seems to me to be obvious stuff: Because you have supplied methods to do so. Just like with any other class.
package Any;
sub new { my $class=shift; bless {},$class }
sub name {
my $self=shift;
my $type=$self->type;
$self->{$type}{name}=shift if @_;
$self->{$type}{name};
}
sub mirror {
my $self=shift;
my $other=$self->other;
my $type=$self->type;
$self->{other}= delete $self->{type};
bless $_[0],$other;
}
sub type { 'neither' };
sub other { 'Any' };
package Leftie;
@ISA=qw(Any);
sub type { 'left' };
sub other { 'Rightie' };
1;
package Rightie;
@ISA=qw(Any);
sub type { 'right' };
sub other { 'Leftie' }
1;
As you can see the two classes actually dont know anything about the others insides at all. Hell, the full behaviour is defined by Any.
Then I'd ask why you wrote this code as OO, since you aren't getting a major benefit of OO: abstraction.
Because I want to take advantage of another benefit of OO - polymorphism?
There are many common approaches for doing the kind of thing you describe that don't require breaking encapsulation.
Yup. But sometimes adding that extra layer of indirection makes things harder to understand rather than simpler, and sometimes breaking encapsulation of implementation doesn't hurt anybody.
I agree that reblessing is usually a sign of a design gone wrong - but sometimes it is the simplest solution. And that's fine with me as long as it doesn't get in the way elsewhere.
The person trying to debug this code later may not agree that doing something so strange and unexpected just to save a few lines was worth it.
Possibly. But the very few occasions I have used the technique the motivation hasn't been to save lines of code. It's been to provide a simpler and clearer solution than the alternatives. I can only hope I succeeded.
Is a valid answer "never, and if I see code that re-blesses, I make sure it gets red flagged"? I didn't see that in your poll, but that's would I would check off.
Re-blessing can be very useful way to inactivate destroy your object while it hasn't been destroyed. Imagine, for example, DBI's database connection handles. For this contrived case, assume that connections never die except by explicit connection from your own side. After $dbh->disconnect, they're mostly useless. If they were blessed into another class, and already cleaned up internally, a check for connection at the beginning of each method is no longer needed. Great for performance, great for keeping your code clean. And the clean code would inspire me to add better diagnostics: instead of just "prepare on an inactive database handle", you could add "(inactive because of ->disconnect in foo.pl line 15)". Possible without reblessing, but not as nice.
Juerd # { site => 'juerd.nl', plp_site => 'plp.juerd.nl', do_not_use => 'spamtrap' }
Some of this flew right over/around my head, but your point seems to be avoiding a call to DESTROY for the original class- so you re-bless them into a class whose purpose it is to recycle the object, then discard of it appropriately. Is this the same as subclassing it to override the DESTROY method, or is there extra niftiness that I'm missing?
Writing such a class would require co-maintaining it with the parent class if you break encapsulation (as merlyn points out) but if that's not a problem, sounds good. I am interested in seeing a less contrived example of what you suggest.
"One is enough. If you are acquainted with the principle, what do you care for the myriad instances and applications?"
- Henry David Thoreau, Walden
Some of this flew right over/around my head, but your point seems to be avoiding a call to DESTROY for the original class- so you re-bless them into a class whose purpose it is to recycle the object, then discard of it appropriately. Is this the same as subclassing it to override the DESTROY method, or is there extra niftiness that I'm missing?
I use this technique to bridge the time in between inactivation and actual destruction: the object is no longer usable (possibly only partly), but there are still references to it, so it hasn't been destroyed yet. If some state (e.g. connected or disconnected) is so important for how an object works, I think it makes sense to not store the state as a property, but by changing the class. It certainly makes programming easier.
There are good reasons to want to inactivate an object before destruction. If you let lexical destruction handle it, you may accidentally keep your heavy active state (connection) until global destruction, which may take hours, days, or even weeks before it happens. Also, if inactivation is just a side-effect of destruction, you can't easily handle things like an ENOSPC in a close. However, when the object is no longer active, you want to be sure that using it properly fails (throws an exception). You could do this by checking the state at the beginning of each method call, but I think it's easier and makes more sense to change the class, and generate methods that croak there.
Recycling objects doesn't work just by reblessing it. You could, however, recycle objects that you have wrapped. But you can do that in a DESTROY method too, so it's not a reblessing specific game. If you want to re-use your $self later, you can use Data::Swap to swap($self, $foo) (where $foo is blessed into the inactive state class), and then store $foo (which after the swap is what $self was before) for re-use.
Writing such a class would require co-maintaining it with the parent class if you break encapsulation (as merlyn points out) but if that's not a problem, sounds good.
Every line of code you write has to maintained. Reblessing can result in having fewer lines to maintain, but it can also result in having to maintain a little more. If you properly inherit methods that work in both/all states, then you don't have code duplication and isa works as expected. I'd generate the methods that croak in a foreach loop, instead of repeating the same code. And, of course, you don't have to break encapsulation. When you do, it may or may not be okay, depending on how you broke it and what part you broke.
Juerd # { site => 'juerd.nl', plp_site => 'plp.juerd.nl', do_not_use => 'spamtrap' }
"One is enough. If you are acquainted with the principle, what do you care for the myriad instances and applications?"
- Henry David Thoreau, Walden
package Facade::Base;
sub new {
my $class = shift;
my ($main) = @_;
return bless \$main, $class;
}
package Facade::One;
use base 'Facade::Base';
sub example {
my $self = shift;
# foo() is a method on the object I expect to facade over
$$self->foo( @args );
}
package main;
my $datastructure = Main::Class->new( %params );
my $facade1 = Facade::One->new( $datastructure );
# Now, I can call Facade::One's methods on $facade1.
# I can also change the facade by doing something like:
my $facade2 = Facade::Two->new( $$facade1 );
"One is enough. If you are acquainted with the principle, what do you care for the myriad instances and applications?"
- Henry David Thoreau, Walden
In Perl 5, blessing is just a way to attach a dispatch table to some data structure. If I want my data structure to behave differently at different points in time the obvious solution is to change its dispatch table accordingly, so reblessing it.
Those controlled manners are at least two:
class TheHulk;
sub new {
bless $self, $class;
$self->go_normal;
$self;
}
sub go_normal {
bless $self, TheHulk::_normal;
}
sub go_green {
bless $self, TheHulk::_green;
}
sub relax {}
sub make_angry {}
package TheHulk::_normal;
sub run {
...
}
sub make_angry {
$self->go_green;
}
package TheHulk::_green;
sub run {
...
}
sub relax {
$self->go_normal;
}
three packages are used, but conceptually is just one class, so there is no messing with the internals of one class from another and the reblessing is always done from inside the class not from the outside.
I am just saying that doing it in a controlled manner is an useful mechanism and it can be used without breaking encapsulation or any other OOP property.
Well said. Just because something is dangerous doesn't mean it can't be used in a positive way.
I think the disconnect between how you're looking at things and how I am looking at things is I see OO as a set of behaviors that, when necessary, has some data to support those behaviors. You're looking at it as a data structure that may or may not have some behaviors associated with it. That's a pretty big disconnect.
Where have you found it useful to re-bless an object?
See Re^7: Informal Poll: Traits (Long Post Warning!) for some previous discussions on the topic.
Ive found reblessing can be useful in a couple of circumstances. One is when dealing with stuff like delayed loading. For instance if you have an object that has a "lite" and a "heavy" representation and the transition from lite to heavy is expensive it can be useful to have the object metamorphize itself from the lite to heavy on demand.
You could do the same thing with an internal if() but then you are duplicating method dispatch in an inefficient way in that you are adding an if() that shouldnt be there.
Another, related use of reblessing is for the purpose of "freezing" an object in a serialization tool. You may have an object that simply cant be represented conveniently in one form, so you define a secondary class with an "unfreeze" method for the purpose. With AUTOLOAD the frozen class can unfreeze itself on demand by converting itself and reblessing when a method is called on it.
As perrin points out elsewhere both of these mean you have tight coupling between the classes, but for these type of purpose thats pretty much a given. I see this in a sense as a specialized form of a factory. And in an object/class factory you also have tight coupling.
A last use for reblessing that I've used is as an attribute on privately created references without using method dispatch on the blessed objects. In that case I see nothing wrong with it at all. It can be convenient at times to use bless as a way to attach an attribute to an arbitrary reference without changing the contents of that reference. Of course you can also add insideout objects but that can be more hassle. It basically depends on which side of the abstraction layer its on, if its totally private to your code i dont see the problem, if it "leaks" past your codes abstraction layer then it probably is a problem.
All of this is for specialized stuff where IMO the normal rules dont necessarily apply. But as a general rule using rebless gratuitiously is IMO unwise
Reblessing is one approach for doing foreign inheritance in inside-out objects without using a facade. For example, what if you want to keep additional state with a filehandle object? The following code is adapted from [mod://File::Marker]:
package File::With::State;
use strict;
use warnings;
use Scalar::Util qw( refaddr );
use base 'IO::File';
my %stash; # hold inside-out state
sub new {
my $class = shift;
# create the object and rebless
my $self = IO::File->new();
bless $self, $class;
# initialize the object
$stash{ refaddr $self } = {};
$self->open( @_ ) if @_;
return $self;
}
sub stash {
my ($self, $key, $value) = @_;
return unless $key;
$stash{ refaddr $self }{ $key } = $value if $value;
return $stash{ refaddr $self }{ $key };
}
# Note: this simple example is not thread-safe and also
# needs a destructor to avoid leaking memory
The advantage of this over the facade pattern is that you can use the object directly wherever you would use a filehandle.
my $fh = File::With::State->new( 'some_file' ); my @lines = <$fh>; $fh->stash( line_count => scalar @lines );
I think this use of reblessing is "safe" because it reblesses into a subclass, which means that all the methods of the original class are available (although they could be overridden as usual with subclassing). No functionality is lost through the reblessing.
-xdg
Code written by xdg and posted on PerlMonks is [http://creativecommons.org/licenses/publicdomain|public domain]. It is provided as is with no warranties, express or implied, of any kind. Posted code may not have been tested. Use of posted code is at your own risk.
perlmonks.org content © perlmonks.org and adrianh, blogical, demerphq, dragonchild, jdporter, Juerd, merlyn, perrin, salva, xdg
prlmnks.org © 2006 edmund von der burg (eccles & toad)
v 0.03