From: Yuval Kogman Date: Mon, 30 Jun 2008 09:54:59 +0000 (+0000) Subject: start a style guide X-Git-Tag: 0_55~72 X-Git-Url: http://git.shadowcat.co.uk/gitweb/gitweb.cgi?a=commitdiff_plain;h=9632a49e67c27a6dd37947a3858a2f25d4d02574;p=gitmo%2FMoose.git start a style guide --- diff --git a/lib/Moose/Cookbook/Style.pod b/lib/Moose/Cookbook/Style.pod new file mode 100644 index 0000000..4a28aaa --- /dev/null +++ b/lib/Moose/Cookbook/Style.pod @@ -0,0 +1,160 @@ +=pod + +=head1 NAME + +Moose::Cookbook::Style - How to cook Moose with style + +=for authors + +Please annotate all bad examples with comments so that they won't be copied by accodent + +=cut + +=head1 Benefits of Good Style + +Good Moose style, as defined by this document, helps ensure your code has the +following desirable properties: + +=over 4 + +=item Play well with others + +Your code will be more reusable and easier to extend. + +=item Ease maintenance + +The code will be easier to understand because it follows an accepted set of +conventions and idioms. + +This will help others maintaining your code, and also help you to get support +on IRC for instance. + +=item Help Moose generate better code + +By using the most appropriate features, the generated code will be safer and +more efficient. + +=item Benefit from meta programming + +Code that operates on the metaclass will benefit from clean meta definitions. + +If you are manually converting argument types with C there is no +meta data explaining your intention. If on the other hand you use coercions, +there is introspectable meta data that makes this clear. + +This means that e.g. MooseX extensions that work by introspecting your class +will be able to do the right thing more often, because they don't need to +guess. + +=back + +=head1 Don't change C + +It is generally considered bad style to override L for a +number of reasons. + +The first reason is consistency. Subclasses of your class and code +instantiating your class would be simpler if your constructor works closer to +the default. + +The second reason is performance. By calling C on your metaclass: + + __PACKAGE__->meta->make_immutable; + +And opting out of any class definition changes from that point on, you allow +Moose to create more efficient versions of certain generic methods. Moose will +generate a tight, optimal C for you, based on the minimal set of features +you use. + +Moose provides many features that allow you to do common object construction +tasks at the right level of abstraction. + +When attributes have the ability to provide the necessary functionality, use +that. If that isn't sufficient, L has numerous features you can +use at construction time. + +=head2 Use C instead of custom initialization or overriding C + +Instead of changing C, do initialization in C. + +The construction parameters are passed in, so you don't need to replicate +C, and since C is called for each superclass that defines it, +you will never forget to invoke your initializers if you extend them. + +=head2 Use C, C or C + +To initialize attributes there is a plethora of methods preferable to assigning +the value at initialization time. + +If you want to translate parameter data, use coercions. + +If you want to ensure a parameter can't be overridden by the constructor, set +the C to C instead of overwriting it in C. + +=head2 Use C to alter C<@_> processing + +If you need to change the way L<@_> is processed, use C, instead of +wrapping C. This ensures the behavior is subclassible, it keeps this logic +independent of the other aspects of construction, and can be made efficient +using C. + +=head1 Don't pollute the global type registry + +=head2 Use fully qualified type names for your own data + +L provides a convenient method to do this. + +If you define + + # Bad style: + + subtype Person => ( + as 'Object', + where { $_->can("name") }, + ); + +Then the global name C is registered, and this could conflict with +other bad usage of the sort. + +Instead, prefix type name with your project namespace, or class name: + + subtype 'My::Foo::Person' => ( + as 'Object', + where { $_->can("name") }, + ); + +Or with L: + + use MooseX::Types ( + -declare => [qw(Person)], + ); + + subtype Person() => ( # note parenthesis, "Person" is a function, not a string + as 'Object', + where { $_->can("name") }, + ); + +Likewise use fully qualified subtypes of other types for defining coercions, so +that they won't affect unrelated code, causing action at a distance. + +This is important because the type registry is global, kind of like the symbol +table. + +This means that code like: + + # Bad style: + + coerce ArrayRef => ( + from Str => via { [ split /,/ ] }, + ); + +Will add a coercion to B attributes like: + + has foo => ( + isa => "ArrayRef", + coerce => 1, + ); + +in a specific way. + +