Encapsulate Behavior, not Just State

From WikiContent

(Difference between revisions)
Jump to: navigation, search
Current revision (17:38, 8 July 2009) (edit) (undo)
 
(6 intermediate revisions not shown.)
Line 1: Line 1:
-
In systems theory containment is one of the most useful constructs when dealing with large and complex system structures. In the software industry the value of containment or encapsulation is well understood, and its supported by programming language constructs such as subroutine, function, module, package, object (class).
+
In systems theory, containment is one of the most useful constructs when dealing with large and complex system structures. In the software industry the value of containment or encapsulation is well understood. Containment is supported by programming language constructs such as subroutines and functions, modules and packages, classes, and so on.
-
Module and package addresses the larger scale needs for encapsulation, while object, subroutine and function addresses the more fine granular aspects of the matter. Over the years I have discovered that objects seams to be one of the hardest encapsulation constructs for developers to get right. It's not seldom you find a class with one single 3000 line main method, or a class with only set and get methods for its primitive attributes. These examples illustrates basically that the developers involved has never understood object oriented thinking, and the power of objects as modeling constructs.
+
Modules and packages address the larger scale needs for encapsulation, while classes, subroutines, and functions address the more fine-grained aspects of the matter. Over the years I have discovered that classes seem to be one of the hardest encapsulation constructs for developers to get right. It's not uncommon to find a class with a single 3000-line main method, or a class with only ''set'' and ''get'' methods for its primitive attributes. These examples demonstrate that the developers involved have not fully understood object-oriented thinking, having failed to take advantage of the power of objects as modeling constructs. For developers familiar with the terms POJO (Plain Old Java Object) and POCO (Plain Old C# Object or Plain Old CLR Object), this was the intent going back to the basic of OO as a modelling paradigm — the objects are plain and simple, but not dumb.
-
An object encapsulates both state and behavior, where the behavior is defined by the actual state. Think of the object door, it has four states: closed, open, closing, opening. It provide two operations: open and close. Dependent of state the open and close operations will behave differently. This inherent property of an object makes the design process conceptual simple. It boils down to two simple tasks: allocation and delegation of responsibility to the different objects including the inter-object interaction protocols.
+
An object encapsulates both state and behavior, where the behavior is defined by the actual state. Consider a door object. It has four states: closed, open, closing, opening. It provides two operations: open and close. Depending on the state, the open and close operations will behave differently. This inherent property of an object makes the design process conceptually simple. It boils down to two simple tasks: allocation and delegation of responsibility to the different objects including the inter-object interaction protocols.
-
How this works in practice is best illustrated by an example. Lets say we have three objects, customer, order and item. The customer object is the natural placeholder of the credit limit and credit validation rules. The order object knows about its associated customer, and its addItem(item) operation delegates the actual credit check by calling customer.validateCredit(item.price()). If the post condition for the method fails, an exception is thrown and the purchase is aborted.
+
How this works in practice is best illustrated with an example. Let's say we have three classes: <code>Customer</code>, <code>Order</code>, and <code>Item</code>. A <code>Customer</code> object is the natural placeholder for the credit limit and credit validation rules. An <code>Order</code> object knows about its associated <code>Customer</code>, and its <code>addItem</code> operation delegates the actual credit check by calling <code>customer.validateCredit(item.price())</code>. If the postcondition for the method fails, an exception can be thrown and the purchase aborted.
-
Less experienced object oriented developers might decide to wrap all the business rules into an object very often referred to as order-manager or order-service. In these designs order, customer and item are treated as records and all logic is factored out of the objects and tied together in one large method with a lot of internal if-then-else constructs. These methods are easilly flawed and almost impossible to maintain. The main reason: The encapsulation is broken.
+
Less experienced object oriented developers might decide to wrap all the business rules into an object very often referred to as <code>OrderManager</code> or <code>OrderService</code>. In these designs, <code>Order</code>, <code>Customer</code>, and <code>Item</code> are treated as little more than record types. All logic is factored out of the classes and tied together in one large, procedural method with a lot of internal if-then-else constructs. These methods are easily broken and are almost impossible to maintain. The reason? The encapsulation is broken.
-
So in the end, never break the encapsulation, and use the power of your favorite object oriented language to maintain it.
+
So in the end, never break the encapsulation, and use the power of your programming language to maintain it.
-
By Einar Landre
+
By [[Einar Landre]]

Current revision

In systems theory, containment is one of the most useful constructs when dealing with large and complex system structures. In the software industry the value of containment or encapsulation is well understood. Containment is supported by programming language constructs such as subroutines and functions, modules and packages, classes, and so on.

Modules and packages address the larger scale needs for encapsulation, while classes, subroutines, and functions address the more fine-grained aspects of the matter. Over the years I have discovered that classes seem to be one of the hardest encapsulation constructs for developers to get right. It's not uncommon to find a class with a single 3000-line main method, or a class with only set and get methods for its primitive attributes. These examples demonstrate that the developers involved have not fully understood object-oriented thinking, having failed to take advantage of the power of objects as modeling constructs. For developers familiar with the terms POJO (Plain Old Java Object) and POCO (Plain Old C# Object or Plain Old CLR Object), this was the intent going back to the basic of OO as a modelling paradigm — the objects are plain and simple, but not dumb.

An object encapsulates both state and behavior, where the behavior is defined by the actual state. Consider a door object. It has four states: closed, open, closing, opening. It provides two operations: open and close. Depending on the state, the open and close operations will behave differently. This inherent property of an object makes the design process conceptually simple. It boils down to two simple tasks: allocation and delegation of responsibility to the different objects including the inter-object interaction protocols.

How this works in practice is best illustrated with an example. Let's say we have three classes: Customer, Order, and Item. A Customer object is the natural placeholder for the credit limit and credit validation rules. An Order object knows about its associated Customer, and its addItem operation delegates the actual credit check by calling customer.validateCredit(item.price()). If the postcondition for the method fails, an exception can be thrown and the purchase aborted.

Less experienced object oriented developers might decide to wrap all the business rules into an object very often referred to as OrderManager or OrderService. In these designs, Order, Customer, and Item are treated as little more than record types. All logic is factored out of the classes and tied together in one large, procedural method with a lot of internal if-then-else constructs. These methods are easily broken and are almost impossible to maintain. The reason? The encapsulation is broken.

So in the end, never break the encapsulation, and use the power of your programming language to maintain it.


By Einar Landre


This work is licensed under a Creative Commons Attribution 3

Back to 97 Things Every Programmer Should Know home page

Personal tools