Moose revealed itself as Good Code to me when I realized that it encourages Good Design. If you follow the example code and use the API it exposes in a natural way, you tend to write well-organized and reasonably safe code (where "safe" means "you paint yourself into fewer corners").

That's the sign of a very good library or framework: the common things are easy and they resulting code is easy to understand, maintain, and extend.

Moose has a very nice feature of reducing the surface area of the APIs you create with it. You can declare a class with several attributes but only expose a few public getters or setters. The ability to use lazy initialization of attributes—as well as default values—allows the calculation of dependent attributes as needed.

Best yet, if you can arrange your classes in such a way as to provide their necessary attribute values when you call their constructors, you can treat your objects from the outside as immutable, and you're halfway toward inversion of control, if that's useful to you.

(Read more about Moose and immutability and the value of these features and designs in the Modern Perl book, available in several freely redistributable electronic forms.)

Think of all of this as not coloring outside the lines. While good art is aware of the structure and limitations of its chosen form and breaks those conventions when it makes for better art, good software is primarily a conversation mechanism where perhaps you don't want to try to outdo Pynchon or DeLillo or Wallace. Perhaps.

Contrast this mechanism of working with objects with the bean style as expressed in parts of the Java world: a class has several private attributes. Each of those attributes has public getters and setters which follow a standard naming convention. Objects interact with other objects by their conformance to a protocol and discovery and use of those getters and setters enabled by the magic genericity of reflection.

(Did anyone else hear a duck quack?)

For the convenience of allowing a dependency injection such as Spring or a web framework inspired by J2EE to manage some of the boilerplate of managing object instantiation or object lifespan or even mapping object data to and from strings for web or web request display, you not only give up the creation of your objects, but you expose their internal attributes behind a thin (and, be honest, autogenerated by your IDE when it pops up a warning!) layer of accessor method.

There is value in the loose and ad hoc adherence to a protocol of practice...

... but for a language which claims great maintainability benefits from forcing the use of static, manifest typing, you may encounter a fair few perplexing errors if you don't get the CamelCase type of your bean property just so. (Remember, reflection!)

While sometimes I do wish Perl 5 were stricter about types and signatures—certainly I look forward to using Perl 6's gradual typing for more projects—I have more sense of safety with the Perl approach, where we don't assume our language is completely safe by itself. We're a little more paranoid, and—at least in this case—I believe it leads to better designs.