8 posts tagged “ironman”
While trying to finish up my thoughts of the followup to "Does Anyone Else Hate the Stash?" one issue that I'm been grappling with is the relationship between using the stash as secondary global namespace and the way I've seen people use the stash as a sort of messaging system to methods called via $c->forward and the like. I guess part of what troubles me here is how doing so seems to bust encapsulation, using the stash as a sort of 'pass by reference' system that reminds more of Perl 4 then where we are at now. I've seen code that forwarded to a method, where the target method expected certain things in the stash but with no interface to really tell you want was expected. That code would forward to other code that expected different things in the stash. And all along all these forwards, stuff gets dropped in and mangled in the stash so by the time it returns from the initial ->forward I really have no idea what is in the stash anymore.
Is this a problem or am I just being too controlling :) Tell me!
So, tell me what you are using forward for, and how you use (or don't use) the stash when doing so. I won't pollute your thoughts on the matter with mine until I've heard from you first :)
And another thing while I'm typing, it seems like all my most popular blog posts contain the word 'Hate" in the title. I may be concerned.
Thanks!
I find as part of my normal course of writing perl moose based code, I do the following quite often:
Basically I tend to use the above with a core application class that is delegating work to several other classes. In the above case, my general Library Class contains a Album class (presumable your library would hold an album and perhaps several other things). In my Application logic I'm going to be calling methods on Album which have been properly normalized to the class which attempt to encapsulate the problem domain it attempts to solve.
I find the above form, although a bit verbose, to give me a lot of flexibility, particularly when I bring the application model into Catalyst via something like Catalyst::Model::Adaptor, which let's me define all the args in the global catalyst configuration. Also, for testing, it's nice to be able to override the default classes, swapping in say a Mock Object or similar for the purposes of test cases.
In general use this construct commonly to avoid hardcoding all the connections between the elements of my applications.
Usage might be like:
Although I as mentioned, typically I instantiate this via Catalyst or as part of a more complicated application using an inversion of control container like Bread::Board.
However it can lead to a little too much verbosity in core application classes, particularly if I have a bunch of these. It's a type of repeated line noise which hides the actual functionality of the class. So I'm considering creating a Moose Parameterized Role to build these for me, something that would work like (as a minimal case):
Useful? What, if anything should I do to make this CPAN worthy? Or are the requirements of this oft repeated task unique enough as to make a usable code generator unfeasible? Or am I the only one doing this (I don't need vanity CPAN modules...)
If you say "Yes", you also owe me a reasonable name (naming things I am not good at...)
When I first started using Perl Catalyst for web application development I felt appalled by how sloppy it seemed to pass important application data around in a secondary global namespace, the Catalyst Stash. I guess it's context global, but it stills seems messy to me in that it seems to poorly replicate features already built into Perl, and for which Perl can help you use correctly. I mean, a global is bad enough, but if you use strict and warnings you will at least get warned if you abuse a global, such as if you try to use it before it's initialized and all that. But the Stash is basically a Hash, and it's prone to typo issues, etc., basically all the evil stuff that I tried to banish from my Perl applications years ago.
It's one of those things that seems fundamentally busted to me, yet it works well enough for simple to medium cases. It just feels to me like it decouples control way too much, and in my experience the stash becomes a sort of no man's land.
I think it's one of the three things that bother me about Catalyst (with the ->forward/go/visit/detach versus method call ambiguity and the way the default TT view guesses a template based on the action name being the other two things that work acceptably enough but still manage to bother me quite a bit).
Thoughts? Am I being too controlling here? Should I just go with the flow or are there others out there that are also bothered by this?
Recently with all the renewed effort on the part of Perl programmers to be better public advocates of our language, I've noticed an uptick in counter productive and quick frankly hateful comments directed at Perl.
I'd really like to find out why. I'd also like to be reasonable and think there's actually something rational behind all this. Several ideas come to mind. For example, is all this negativity based on Perl's perception as spagetti code? Is that just rumor or have many of you out there been required to step in and take over projects with difficult codebases? Is it due to the fact that Perl 6 is still in development? Has it to do with something many of you have experienced on the job? Or maybe you've tried to get help from various Perl communities and gotten flamed?
I really have trouble understanding where this is coming from. Personally, I use Perl because I find it works with my brain and not against it. I've not found this to be the case with PHP, Python or Ruby. I have nothing against any of those languages, but it makes little sense for me to force myself to relearn and rebuild my current skillset in a different language that doesn't really offer me a compelling reason to do so. I'm deeply invested into the Perl community as a contributer to several important open source projects and that's what I enjoy about my job.
However the negativity is something I'd like to address if possible, because all this hate directed at Perl can affect me personally in terms of future employment and job options. This directly affects my family, my wife, son and dog, so I take it very seriously.
Because to be quite honest, the combined popularity of the most common scripting languages doesn't come close to countering the Java/C# juggernaut, and as someone committed to open source / free software this is an additional worry for me. Neither of those languages are particularly committed to software freedom. As far as I am concerned Sun (or Oracle now I guess) and Microsoft give some lip service to software freedom since that's a popular thing nowadays, but it's minimal and tactical in nature. Free free to argue with me if you think I'm wrong, but I just don't see a deep and fundamental commitment. Now, maybe you don't care about software freedom, but I'm old enough to remember the days when being a programmer nearly always involved proprietary tool chains and expensive certifications. If it wasn't for the threat posed by developers and advocates of free software there would be no Java Community Process, no Mono, nor would there likely be quality free version of IDEs like NetBeans, Eclipse or the various free 'Express' versions from Microsoft. There would be no free, online versions of documentation. So it really seems to be we should be working together, not against each other.
Several possible points of collaboration that suggest themselves would be standards for testing, deployment and management of applications. Also, we often depend on a core set of external libraries, such as MemcacheD, xml and xslt parsing libraries and so forth. It would be great if we worked together to improve these and to ensure that the language bindings were of consistent and high quality.
Each of our communities has different strengths and weaknesses. The Rails group are great at advocacy and Ruby has a reputation for delivering nice, clean code. Python really focuses well on education and ramping up newcomers. Perl has great testing and deployment tools, as well as CPAN. Why are sniping each other when working together would have so many benefits?
So in my attempt to add in some support for Dependent Type programming to Perl Moose programming I'm at the part where I need to integrate this into declaring your Moose based Perl objects. To recap, with a Dependent Type Constraint you can declare a constraint like:
subtype Range,
as Dict[max=>Int, min=>Int],
where {
my $range = shift @_;
return $range->{max} > $range->{min};
};
subtype RangedInt,
as Dependent[Int, Range],
where {
my ($int,$range) = @_;
return ($int >= $range->{min} && $int <= $range->{max});
};
RangedInt([max=>10, min=>1])->check(5); ## Is fine
RangedInt([max=>10, min=>1])->check(15); ## Is NOT fine
You can then use this in a Perl class like so:
class MyClass {
has young_adult_age => ( is=>'ro', isa=>RangedInt[min=>18,max=>34] );
}
And you can instantiate this like so:
MyClass->new(young_adult_age=>20);
But the following will throw an exception:
MyClass->new(young_adult_age=>40);
Also, if you are using MooseX::Declare you can use these in your method body signatures:
method height(RangedInt[min=>10,max=>100] $height) { ## Do something here }
All this is supported in the current repository version you can review here.
So far so good. However, it's been requested to be able to fulfill a dependency requirement via $self when using dependent types in a class. My proposed syntax for this is to make the 'isa' and 'does' attribute options similar to default, where if the attribute is lazy and the value is a coderef, we de-reference it and pass $self. So, for example, let's say you create some type constraints and a class that uses it like so:
use Set::Scalar;
use Email::Valid;
subtype Email,
as Str,
where {
return Email::Valid->address($_);
};
subtype Set,
as Dependent[class_type 'Set::Scalar', Any],
where {
my ($set, $item) = @_;
foreach my $element ($set->members) {
return unless $item->check($element);
} 1
}
subtype UniqueEmail,
as Dependent[Email, Set],
where {
my ($email, $set) = @_;
return !$set->has($email);
}
class Person {
has email_set => (is=>'ro', isa=>Set[Email] );
has email => (is=>'ro', isa=>UniqueEmail[Set[Email]] );
}
Ideally, when you try to instantiate this class, the attribute 'email' would be bound to attribute 'email_set', in such a way that it's value should be unique in that set. To achieve this, I am proposing an attribute trait that allows something like:
class Person {
has email_set => (is=>'ro', isa=>Set[Email] );
has email => (
is=>'ro',
isa=>sub {
my $self = shift @_;
my $set = $self->email_set;
return UniqueEmail[$set];
},
traits=>['Dependent'],
);
}
And at validate time, the coderef would be dereferenced with $self, similarly to the way the default option works. We'd do the same for the 'does' attribute. And to make it even more similar to default, I'd support coderefs here without lazy, which would not pass $self, but would execute at runtime.
For myself, I'd rather have another solution, but maybe I just don't fully grasp the use cases. Comments on the above proposals very welcome. However, if you are wanting something very different, you should give me enough specification for me to get it.
==UPDATES==
It's been suggested that instead of overloading 'does' and 'isa', to use a new options, such as 'generate_isa' or similar. Should be more sane and play nicer with other attributes that expect isa and does to behave a certain way.
One thing which has come up from time to time on the Moose Type Constraint wish list is the ability to more easily define type parameters. For example, it would be great if we could very simple create an Integer type that is bound by a range. For example:
subtype Range,
as Dict[max=>Int, min=>Int],
where {
my $range = shift @_;
return $range->{max} > $range->{min};
};
subtype RangedInt,
as Dependent[Int, Range],
where {
my ($int,$range) = @_;
return ($int >= $range->{min} && $int <= $range->{max});
};
class MyClass {
has young_adult_age => ( is=>'ro', isa=>RangedInt[min=>18,max=>34] );
}
And you can instantiate this like so:
MyClass->new(young_adult_age=>20);
But the following will throw an exception:
MyClass->new(young_adult_age=>40);
This gives your Moose based Perl programming a bit more flexibility!
Right now this is not on CPAN, but you can see it, play with it (and help me shed light on any of the corner cases) at: https://jules.scsys.co.uk/gitweb/gitweb.cgi?p=gitmo/MooseX-Dependent.git;a=tree
At this point the code is shaping up, although there's a bit of ugly stuff in the type constraint code. Even coercions work as you might hope.
Pending responses to the above syntax, remaining things before CPAN is primarily some attribute traits so that we can expose $self to a dependent type in a class. This would allow something like:
class Person {
has people => (is=>'ro', isa=>PeopleResultSet, required=>1);
has id => (is=>'ro', is=>UniqueID[PeopleResultSet], traits=>['Dependent']);
}
The idea being that the attribute 'id' would be bound to the attribute 'people' so that you could not create a new Person that had a pre-existing ID. The attribute trait stuff is still pending and feedback, test cases / use cases and of course code are very welcome.
UPDATED: My apologies for rebranding the date to anyone who has a working aggregator, but seems that whatever the settings for the Ironman aggregator, it wasn't picking up my post. Maybe I'm supposed to say, "Perl Programming now..."
10. It's Getting Great Press!
I can't remember the last time a Perl module has generated so much discussion, whether in blogs, at conferences or just in general. People who use it nearly always become advocates. Here's a few I was reading just recently:
- http://blog.jrock.us/articles/Myth:%20Moose%20is%20an%20unnecessary%20dependency.pod
- http://avatraxiom.livejournal.com/70947.html
- http://transfixedbutnotdead.com/2008/03/12/doodling-with-moose-part-1/
You would not have to look hard to find many, many more.
9. Makes Creating Objects Fast an Easy!
Whether you are using 'classic' Moose or playing with the new MooseX::Declare I have never used an object system that was so easy and felt like it belonged to Perl. In the best tradition of Perl it makes easy things easy to do, and make the impossible doable. All this with minimal boilerplate.
Not convinced? Check out this comparison of all the stuff you need to write to make a non Moose Perl object approach the functionality of what you get out of the box with Moose.
8. Makes Perl Objects Powerful!
Moose is built on top of a well researched and highly respected Meta Object Protocol which means Moose objects and the framework and software ecosystem being built around it are on very firm foundations. We've been developing on and in Moose for more than three years now and the concepts underlying it are not showing signs of weakness. Usually by now people would be talking of a 'rewrite to get it right' but clearly Moose is pretty right as it is. As a result we can focus our attention on expanding MooseX modules and on advocacy and documentation. Clearly, Moose is the most powerful object system for Perl and is a heavyweight in comparison to other languages with strong object oriented features.
7. Moose Attributes
Removing all the boilerplate associated with creating object attribute reader/writer methods, as well as making it easy to apply type constraints (see for more) was probably the thing that got me interested in Moose to begin with. If Moose only did this, it would still be useful. That fact that this feature is just a small one among many is mind blowing.
6. Moose Baked in Type Constraints and Coercions
Although I've always loved that Perl is a dynamic language, I've often wished it was easier to validate arguments and attributes. There's probably been a dozen or more such systems on CPAN, but Moose Type Constraints mixes the perfect blend of usefulness and wide adoption that met my immediate need while growing with me as a developer. Now I'm a Type Constraint junkie, who spends him time researching more and more esoteric type constraint concepts.
5. Moose Roles are Awesome!
I could say more, but someone smarter has recently done a blog series about Moose Roles that I highly recommend you check out.
4. MooseX
Do a search for "MooseX" on CPAN (here for example) and you are going to get a ton of useful things. This points out not only the energy and excitement of the community, but serves as more proof that Moose was 'done right' the first time. the For a list of recommended MooseX modules see this article.
3. Great Moose Inspired Stuff!
There's more and more stuff showing up on CPAN that is Moose inspired. For example, the recent Catalyst port has revitalized development on this important web application project. Or check out KiokuDB if you are looking for a fast and easy way to persistent your objects. If you are interested in a cutting edge user interface and interface modeling system, see Reaction. I've only scratched the surface here.
2. Documentation, Tests and Online Tutorials.
When I got to Moose, I found there was not only reasonable documentation to help with with the basics, but also a straightforward tutorial that showed how to go about building applications the Moose way. It definitely helped me to grasp the essential bits and it got me started very quickly on the features I found most useful and time saving. For me this was the key to adopting Moose and the online docs really show you the heavy benefits right off the top.
When I needed more examples, I could go straight to the test directory and find scores of useful tests that showed how the system worked as well as provided me very useful code samples.
And the Number One Great Thing about Moose...
1. The Community!
Not only would all the above not be possible without the tireless and creative effort of the group of core developers, but this community has really reached out and brought lots of people into the fold. They are greatly responsive to bug reports and feature requests, maintaining a pace of releases that is truly amazing. This community also has some of the smartest people I've ever had the pleasure to work with. I definitely feel being part of the Moose community has not only made me a better programmer, but a better person as well.
- Mailing List Info
- IRC Chats (Join Channel #moose on irc.perl.org)