ToInstance no longer needs to subclass ToClass
[gitmo/Moose.git] / lib / Moose / Manual / BestPractices.pod
index 56c9709..f0edc9b 100644 (file)
@@ -13,39 +13,46 @@ 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.
 
-=head2 C<no Moose> and immutabilize
+=head2 C<namespace::autoclean> and immutabilize
 
-We recommend that you end your Moose class definitions by removing the
-Moose sugar and making your class immutable.
+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;
 
-The C<no Moose> bit is simply good code hygiene, and making classes
-immutable speeds up a lot of things, most notably object construction.
+The C<use namespace::autoclean> bit is simply good code hygiene, as it removes
+imported symbols from  you 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 needed. 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.
+
+C<no Moose;> may be used to unimport only Moose's imported symbols.
+L<namespace::clean> provides finer-grained control than L<namespace::autoclean>. 
 
 =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.
+class is immutabilized.
 
-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.
+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
 ;)
@@ -84,7 +91,7 @@ Also, keep your builder methods private.
 
 Lazy is good, and often solves initialization ordering problems. It's
 also good for deferring work that may never have to be done. If you're
-going to be lazy, use I<lazy_build> to save yourself some typing and
+going to be lazy, use C<lazy_build> to save yourself some typing and
 standardize names.
 
 =head2 Consider keeping clearers and predicates private
@@ -106,6 +113,15 @@ 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
@@ -116,13 +132,12 @@ of object in the parent class.
 
 Don't know what we're talking about? That's fine.
 
-=head2 Use L<MooseX::AttributeHelpers> instead of C<auto_deref>
+=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<MooseX::AttributeHelpers> to define an API that exposes those pieces
-of functionality that need exposing. Then you can expose just the
-functionality that you want.
+L<Moose::Meta::Attribute::Native> traits to define an API that exposes only
+necessary pieces of functionality.
 
 =head2 Always call C<inner> in the most specific subclass
 
@@ -134,8 +149,11 @@ changing the parents.
 =head2 Namespace your types
 
 Use some sort of namespacing convention for type names. We recommend
-something like "MyApp.Type.Foo". I<Never> use "::" as the namespace
-separator, since that overlaps with actual class names.
+something like "MyApp::Type::Foo".
+
+If you're intending to package your types up for re-use using
+L<MooseX::Types> later, avoid using characters that are invalid in
+perl identifiers such as a space or period.
 
 =head2 Do not coerce Moose built-ins directly
 
@@ -146,15 +164,15 @@ type.
     # very naughty!
     coerce 'ArrayRef'
         => from Str
-            => via { [ split /,/ ] };
+        => via { [ split /,/ ] };
 
 Instead, create a subtype and coerce that:
 
-    subtype 'My.ArrayRef' => as 'ArrayRef';
+    subtype 'My::ArrayRef' => as 'ArrayRef';
 
-    coerce 'My.ArrayRef'
+    coerce 'My::ArrayRef'
         => from 'Str'
-            => via { [ split /,/ ] };
+        => via { [ split /,/ ] };
 
 =head2 Do not coerce class names directly
 
@@ -165,15 +183,15 @@ have magical side effects elsewhere:
     # also very naughty!
     coerce 'HTTP::Headers'
         => from 'HashRef'
-            => via { HTTP::Headers->new( %{$_} ) };
+        => via { HTTP::Headers->new( %{$_} ) };
 
 Instead, we can create an "empty" subtype for the coercion:
 
-    subtype 'My.HTTP::Headers' => as class_type('HTTP::Headers');
+    subtype 'My::HTTP::Headers' => as class_type('HTTP::Headers');
 
-    coerce 'My.HTTP::Headers'
+    coerce 'My::HTTP::Headers'
         => from 'HashRef'
-            => via { HTTP::Headers->new( %{$_} ) };
+        => via { HTTP::Headers->new( %{$_} ) };
 
 =head2 Use coercion instead of unions
 
@@ -204,7 +222,7 @@ 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
+metadata. This sort of thing is particularly problematic for MooseX
 extensions which rely on introspection to do the right thing.
 
 =head1 AUTHOR