Skip to content

Latest commit

 

History

History
126 lines (94 loc) · 5.21 KB

advanced_oo.pod

File metadata and controls

126 lines (94 loc) · 5.21 KB

Advanced OO Perl

Creating and using objects in Perl 5 with Moose (moose) is easy. Designing good programs is not. You must balance between designing too little and too much. Only practical experience can help you understand the most important design techniques, but several principles can guide you.

Favor Composition Over Inheritance

Novice OO designs often overuse inheritance to reuse code and to exploit polymorphism. The result is a deep class hierarchy with responsibilities scattered in the wrong places. Maintaining this code is difficult--who knows where to add or edit behavior? What happens when code in one place conflicts with code declared elsewhere?

Inheritance is but one of many tools. Although Car may extend Vehicle::Wheeled (an is-a relationship), it's likely better for Car to contain contain several Wheel objects as instance attributes (a has-a relationship).

Decomposing complex classes into smaller, focused entities (whether classes or roles) improves encapsulation and reduces the possibility that any one class or role will grow to do too much. Smaller, simpler, and better encapsulated entities are easier to understand, test, and maintain.

Single Responsibility Principle

When you design your object system, consider the responsibilities of each entity. For example, an Employee object may represent specific information about a person's name, contact information, and other personal data, while a Job object may represent business responsibilities. Separating these entities in terms of their responsibilities allows the Employee class to consider only the problem of managing information specific to who the person is and the Job class to represent what the person does. (Two Employees may have a Job-sharing arrangement, for example.)

When each class has a single responsibility, you improve the encapsulation of class-specific data and behaviors and reduce coupling between classes.

Don't Repeat Yourself

Complexity and duplication complicate development and maintenance. The DRY principle (Don't Repeat Yourself) is a reminder to seek out and to eliminate duplication within the system. Duplication exists in data as well as in code. Instead of repeating configuration information, user data, and other artifacts within your system, create a single, canonical representation of that information from which you can generate the other artifacts.

This principle helps to reduce the possibility that important parts of your system can get unsynchronized, and helps you to find the optimal representation of the system and its data.

Liskov Substitution Principle

The Liskov substitution principle suggests that you should be able to substitute a specialization of a class or a role for the original without violating the API of the original. In other words, an object should be as or more general with regard to what it expects and at least as specific about what it produces.

Imagine two classes, Dessert and its child class PecanPie. If the classes follow the Liskov substitution principle, you can replace every use of Dessert objects with PecanPie objects in the test suite, and everything should passSee Reg Braithwaite's "IS-STRICTLY-EQUIVALENT-TO-A" for more details, http://weblog.raganwald.com/2008/04/is-strictly-equivalent-to.html..

Subtypes and Coercions

Moose allows you to declare and use types and extend them through subtypes to form ever more specialized descriptions of what your data represents and how it behaves. These type annotations help verify that the data on which you want to work in specific functions or methods is appropriate and even to specify mechanisms by which to coerce data of one type to data of another type.

See Moose::Util::TypeConstraints and MooseX::Types for more information.

Immutability

OO novices often treat objects as if they were bundles of records which use methods to get and set internal values. This simple technique leads to the unfortunate temptation to spread the object's responsibilities throughout the entire system.

With a well-designed object, you tell it what to do and not how to do it. As a rule of thumb, if you find yourself accessing object instance data (even through accessor methods), you may have too much access to an object's internals.

One approach to preventing this behavior is to consider objects as immutable. Provide the necessary data to their constructors, then disallow any modifications of this information from outside the class. Expose no methods to mutate instance data. The objects so constructed are always valid after their construction and cannot become invalid through external manipulation. This takes tremendous discipline to achieve, but the resulting systems are robust, testable, and maintainable.

Some designs go as far as to prohibit the modification of instance data within the class itself, though this is much more difficult to achieve.

POD ERRORS

Hey! The above document had some coding errors, which are explained below:

Around line 3:

A non-empty Z<>

Around line 75:

Deleting unknown formatting code N<>

Deleting unknown formatting code U<>

Around line 84:

A non-empty Z<>

A non-empty Z<>

Around line 103:

A non-empty Z<>