[Moose-commits] r7613 - in Moose/trunk/lib/Moose: Cookbook Manual

autarch at code2.0beta.co.uk autarch at code2.0beta.co.uk
Wed Feb 11 19:19:54 GMT 2009


Author: autarch
Date: 2009-02-11 11:19:54 -0800 (Wed, 11 Feb 2009)
New Revision: 7613

Modified:
   Moose/trunk/lib/Moose/Cookbook/Style.pod
   Moose/trunk/lib/Moose/Manual/BestPractices.pod
Log:
Merged the content from Moose::Cookbook::Style into
Moose::Manual::BestPractices, and made the former a pointer to the
latter.

Modified: Moose/trunk/lib/Moose/Cookbook/Style.pod
===================================================================
--- Moose/trunk/lib/Moose/Cookbook/Style.pod	2009-02-11 19:19:08 UTC (rev 7612)
+++ Moose/trunk/lib/Moose/Cookbook/Style.pod	2009-02-11 19:19:54 UTC (rev 7613)
@@ -2,208 +2,12 @@
 
 =head1 NAME
 
-Moose::Cookbook::Style - The latest in trendy Moose cuisine
+Moose::Cookbook::Style - Expanded into Moose::Manual::BestPractices, so go read that
 
-=for authors
+=head1 DESCRIPTION
 
-Please annotate all bad examples with comments so that they won't be copied by
-accident
+The style cookbook has been replaced by
+L<Moose::Manual::BestPractices>. This POD document still exists for
+the benefit of anyone out there who might've linked to it in the past.
 
 =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<around 'new'> 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<new>
-
-It is generally considered bad style to override L<Moose::Object/new> 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<make_immutable> 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<new> 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<Moose::Object> has numerous features you can
-use at construction time.
-
-=head2 Use C<BUILD> instead of custom initialization or overriding C<new>
-
-Instead of changing C<new>, do initialization in C<BUILD>.
-
-The construction parameters are passed in, so you don't need to replicate
-C<BUILDARGS>, and since C<BUILD> is called for each superclass that defines it,
-you will never forget to invoke your initializers if you extend them.
-
-=head2 Use C<default>, C<builder> or C<lazy_build>
-
-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<init_arg> to C<undef> instead of overwriting it in C<BUILD>.
-
-=head2 Use C<BUILDARGS> to alter C<@_> processing
-
-If you need to change the way C<@_> is processed, for example for
-C<< Class->new( $single_param ) >>, use C<BUILDARGS> instead of wrapping
-C<new>. This ensures the behavior is subclassable, it keeps this logic
-independent of the other aspects of construction, and can be made efficient
-using C<make_immutable>.
-
-=head1 Don't pollute the global type registry
-
-=head2 Use fully qualified type names for your own data
-
-L<MooseX::Types> provides a convenient method to do this.
-
-If you define
-
-    # Bad style:
-
-    subtype Person => (
-        as 'Object',
-        where { $_->can("name") },
-    );
-
-Then the global name C<Person> 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<MooseX::Types>:
-
-    use MooseX::Types::Moose qw(Object);
-
-    use MooseX::Types (
-        -declare => [qw(Person)],
-    );
-    
-    subtype Person() => ( # note parenthesis, "Person" is a function, not a string
-        as Object, # MooseX::Types::Moose exported it
-        where { $_->can("name") },
-    );
-
-=head3 Coerce in a subtype
-
-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<all> attributes like:
-
-    has foo => (
-        isa => "ArrayRef",
-        coerce => 1,
-    );
-
-when the actual coercion applies only to your specific cases.
-
-=head1 Clean up your package
-
-Use C<namespace::clean> or C<no Moose> to remove the sugar exports.
-
-This will make sure the sugar isn't accidentally called as methods on your objects.
-
-For instance:
-
-    $obj->can("has");
-
-will return true, even though C<has> is not a method.
-
-If you choose L<namespace::clean>, make sure to keep the C<meta> method if you
-want to use it for introspection:
-
-    use namespace::clean -except => "meta";
-
-=head1 Accept no substitutes
-
-By substitutes I mean hacks instead of "proper" solutions.
-
-When you have a tricky requirement, refrain from abusing Moose or MooseX:: or
-whatever it is you are using.
-
-Instead, drop by IRC and discuss it. Most of the time a crazy idea can either
-be simplified, or it will spawn a clean, reliable feature to whatever package
-you are using.
-
-This will improve your code and also share the benefit with others.
-
-=head1 AUTHOR
-
-Yuval (nothingmuch) Kogman
-
-=head1 COPYRIGHT AND LICENSE
-
-Copyright 2006-2009 by Infinity Interactive, Inc.
-
-L<http://www.iinteractive.com>
-
-This library is free software; you can redistribute it and/or modify it under
-the same terms as Perl itself.
-
-=cut

Modified: Moose/trunk/lib/Moose/Manual/BestPractices.pod
===================================================================
--- Moose/trunk/lib/Moose/Manual/BestPractices.pod	2009-02-11 19:19:08 UTC (rev 7612)
+++ Moose/trunk/lib/Moose/Manual/BestPractices.pod	2009-02-11 19:19:54 UTC (rev 7613)
@@ -35,6 +35,21 @@
 The C<no Moose> bit is simply good code hygiene, and making classes
 immutable speeds up a lot of things, most notably object construction.
 
+=head2 Never override C<new>
+
+Overriding C<new> is a very bad practice. Instead, you should use a
+C<BUILD> or C<BUILDARGS> methods to do the same thing. When you
+override C<new>, Moose can no longer inline a constructor when your
+class is immutablized.
+
+The only reason to override C<new> is if you are writing a MooseX
+extension that provides its own L<Moose::Object> subclass I<and> a
+subclass of L<Moose::Meta::Method::Constructor> to inline the
+constructor.
+
+If you know how to do that, you know when to ignore this best practice
+;)
+
 =head2 Always call C<SUPER::BUILDARGS>
 
 If you override the C<BUILDARGS> method in your class, make sure to
@@ -45,10 +60,16 @@
 list and hashref of named parameters correctly, and also checks for a
 I<non-hashref> single argument.
 
-=head2 Don't use the C<initializer> feature
+=head2 Provide defaults whenever possible, otherwise use C<required>
 
-Don't know what we're talking about? That's fine.
+When your class provides defaults, this makes constructing new objects
+simpler. If you cannot provide a default, consider making the
+attribute C<required>.
 
+If you don't do either, an attribute can simply be left unset,
+increasing the complexity of your object, because it has more possible
+states that you or the user of your class must account for.
+
 =head2 Use C<builder> instead of C<default> most of the time
 
 Builders can be inherited, they have explicit names, and they're just
@@ -91,6 +112,10 @@
 itself, at least make sure that it has the same interface as the type
 of object in the parent class.
 
+=head2 Don't use the C<initializer> feature
+
+Don't know what we're talking about? That's fine.
+
 =head2 Use L<MooseX::AttributeHelpers> instead of C<auto_deref>
 
 The C<auto_deref> feature is a bit troublesome. Directly exposing a
@@ -112,8 +137,46 @@
 something like "MyApp.Type.Foo". I<Never> use "::" as the namespace
 separator, since that overlaps with actual class names.
 
-=head2 Coercion instead of unions
+=head2 Do not coerce Moose built-ins directly
 
+If you define a coercion for a Moose built-in like C<ArrayRef>, this
+will affect every application in the Perl interpreter that uses this
+type.
+
+    # very naughty!
+    coerce 'ArrayRef'
+        => from Str
+            => via { [ split /,/ ] };
+
+Instead, create a subtype and coerce that:
+
+    subtype 'My.ArrayRef' => as 'ArrayRef';
+
+    coerce 'My.ArrayRef'
+        => from 'Str'
+            => via { [ split /,/ ] };
+
+=head2 Do not coerce class names directly
+
+Just as with Moose built-in types, a class type is global for the
+entire interpreter. If you add a coercion for that class name, it can
+have magical side effects elsewhere:
+
+    # also very naughty!
+    coerce 'HTTP::Headers'
+        => from 'HashRef'
+            => via { HTTP::Headers->new( %{$_} ) };
+
+Instead, we can create an "empty" subtype for the coercion:
+
+    subtype 'My.HTTP.Headers' => as class_type('HTTP::Headers');
+
+    coerce 'My.HTTP.Headers'
+        => from 'HashRef'
+            => via { HTTP::Headers->new( %{$_} ) };
+
+=head2 Use coercion instead of unions
+
 Consider using a type coercion instead of a type union. This was
 covered at length in L<Moose::Manual::Types>.
 
@@ -122,8 +185,32 @@
 Define all your types and coercions in one module. This was also
 covered in L<Moose::Manual::Types>.
 
+=head1 BENEFITS OF BEST PRACTICES
+
+Following these practices has a number of benefits.
+
+It helps ensure that your code will play nice with others, making it
+more reusable and easier to extend.
+
+Following an accepted set of idioms will make maintenance easier,
+especially when someone else has to maintain your code. It will also
+make it easier to get support from other Moose users, since your code
+will be easier to digest quickly.
+
+Some of these practices are designed to help Moose do the right thing,
+especially when it comes to immutabilization. This means your code
+will be faster when immutabilized.
+
+Many of these practices also help get the most out of meta
+programming. If you used an overridden C<new> to do type coercion by
+hand, rather than defining a real coercion, there is no introspectable
+metadata. This sort of thing is particuarly problematic MooseX
+extensions which rely on introspection to do the right thing.
+
 =head1 AUTHOR
 
+Yuval (nothingmuch) Kogman
+
 Dave Rolsky E<lt>autarch at urth.orgE<gt>
 
 =head1 COPYRIGHT AND LICENSE




More information about the Moose-commits mailing list