Rename Extending::Recipe4 to Extending::Mooseish_MooseSugar
[gitmo/Moose.git] / lib / Moose / Manual / BestPractices.pod
index ef2236c..bdf5ffe 100644 (file)
+package Moose::Manual::BestPractices;
+
+# ABSTRACT: Get the most out of Moose
+
+__END__
+
+=pod
 
 =head1 RECOMMENDATIONS
 
-=head2 No Moose and Immutabilize
+Moose has a lot of features, and there's definitely more than one way
+to do it. However, we think that picking a subset of these features
+and using them consistently makes everyone's life easier.
+
+Of course, as with any list of "best practices", these are really just
+opinions. Feel free to ignore us.
 
-We recommend that you end your Moose class definitions by removing the
-Moose sugar and making your class immutable.
+=head2 C<namespace::autoclean> and immutabilize
+
+We recommend that you remove the Moose sugar and end your Moose class
+definitions by making your class immutable.
 
   package Person;
 
   use Moose;
+  use namespace::autoclean;
 
   # extends, roles, attributes, etc.
 
   # methods
 
-  no Moose;
-
   __PACKAGE__->meta->make_immutable;
 
   1;
 
-=head2 Always call SUPER::BUILDARGS
+The C<use namespace::autoclean> bit is simply good code hygiene, as it removes
+imported symbols from your class's namespace at the end of your package's
+compile cycle, including Moose keywords.  Once the class has been built, these
+keywords are not needed. (This is preferred to placing C<no Moose> at the end
+of your package).
+
+The C<make_immutable> call allows Moose to speed up a lot of things, most
+notably object construction. The trade-off is that you can no longer change
+the class definition.
+
+=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 immutabilized.
+
+There are two good reasons to override C<new>. One, 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. Two, you are subclassing a non-Moose parent.
+
+If you know how to do that, you know when to ignore this best practice
+;)
+
+=head2 Always call the original/parent C<BUILDARGS>
+
+If you C<override> the C<BUILDARGS> method in your class, make sure to play
+nice and call C<super()> to handle cases you're not checking for explicitly.
+
+The default C<BUILDARGS> method in L<Moose::Object> handles both a
+list and hashref of named parameters correctly, and also checks for a
+I<non-hashref> single argument.
+
+=head2 Provide defaults whenever possible, otherwise use C<required>
+
+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
+plain cleaner.
+
+However, I<do> use a default when the default is a non-reference,
+I<or> when the default is simply an empty reference of some sort.
+
+Also, keep your builder methods private.
+
+=head2 Be C<lazy>
+
+Lazy is good, and often solves initialization ordering problems. It's also
+good for deferring work that may never have to be done. Make your attributes
+C<lazy> unless they're C<required> or have trivial defaults.
+
+=head2 Consider keeping clearers and predicates private
+
+Does everyone I<really> need to be able to clear an attribute?
+Probably not. Don't expose this functionality outside your class
+by default.
+
+Predicates are less problematic, but there's no reason to make your
+public API bigger than it has to be.
+
+=head2 Default to read-only, and consider keeping writers private
+
+Making attributes mutable just means more complexity to account for in
+your program. The alternative to mutable state is to encourage users
+of your class to simply make new objects as needed.
+
+If you I<must> make an attribute read-write, consider making the
+writer a separate private method. Narrower APIs are easy to maintain,
+and mutable state is trouble.
+
+In order to declare such attributes, provide a private C<writer>
+parameter:
+
+    has pizza => (
+        is     => 'ro',
+        isa    => 'Pizza',
+        writer => '_pizza',
+    );
+
+=head2 Think twice before changing an attribute's type in a subclass
+
+Down this path lies great confusion. If the attribute is an object
+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<Moose::Meta::Attribute::Native> traits instead of C<auto_deref>
+
+The C<auto_deref> feature is a bit troublesome. Directly exposing a complex
+attribute is ugly. Instead, consider using L<Moose::Meta::Attribute::Native>
+traits to define an API that only exposes the necessary pieces of
+functionality.
+
+=head2 Always call C<inner> in the most specific subclass
+
+When using C<augment> and C<inner>, we recommend that you call
+C<inner> in the most specific subclass of your hierarchy. This makes
+it possible to subclass further and extend the hierarchy without
+changing the parents.
+
+=head2 Namespace your types
+
+Use some sort of namespacing convention for type names. We recommend something
+like "MyApp::Type::Foo". We also recommend considering L<MooseX::Types>.
+
+=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:
 
-=head2 No complex subs for a default, use a builder
+    # also very naughty!
+    coerce 'HTTP::Headers'
+        => from 'HashRef'
+        => via { HTTP::Headers->new( %{$_} ) };
 
-builders can be inherited, show up more cleanly in profile
+Instead, we can create an "empty" subtype for the coercion:
 
-=head2 use default for simple scalar, and empty refs
+    subtype 'My::HTTP::Headers' => as class_type('HTTP::Headers');
 
-=head2 use builder for everything else
+    coerce 'My::HTTP::Headers'
+        => from 'HashRef'
+        => via { HTTP::Headers->new( %{$_} ) };
 
-don't use initializer
+=head2 Use coercion instead of unions
 
-=head2 use lazy_build
+Consider using a type coercion instead of a type union. This was
+covered in L<Moose::Manual::Types>.
 
-keep builders private
+=head2 Define all your types in one module
 
-consider keeping clearers & predicates private
+Define all your types and coercions in one module. This was also
+covered in L<Moose::Manual::Types>.
 
-consider keeping writers private
+=head1 BENEFITS OF BEST PRACTICES
 
-=head2 Think Twice Before Changing an Attribute's Type in a Subclass
+Following these practices has a number of benefits.
 
-=head2 use MX::AH instead of auto_deref
+It helps ensure that your code will play nice with others, making it
+more reusable and easier to extend.
 
-=head2 Namespace Your Types
+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.
 
-and don't use "::"
+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.
 
-=head2 Coercion Instead of Unions
+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 particularly problematic for MooseX
+extensions which rely on introspection to do the right thing.
 
-=head2 Define All Your Types in One Module
+=cut