Friday, October 23, 2009

14.1 Partitioning Control




I l@ve RuBoard









14.1 Partitioning Control


The first rule of partitioning control is you do not make controller objects.


The second rule of partitioning control is you do not make controller objects.[1]


[1] With apologies to Chuck Palahniuk [1].


A controller object comes about when developers create objects to match use cases. As an example of poor partitioning�actually, no partitioning at all�see the single Order Controller class in Figure 14.1, which controls an entire use case for making and fulfilling an order. All communication goes through the Order Controller, which "simplifies" the collaboration diagram, but leaves the order controller with a very large statechart diagram.


Figure 14.1. Mongo Controller Object (Bad Design�No Control Partitioning)



The statechart diagrams of the objects�the real order, the charge, and the shipment�tend to be trivially simple, but that of the controller object is large and complex. These controller statechart diagrams quickly become unmanageable as we incrementally develop the domain.


We recommend against a single controller object for this reason.


The single controller is an extreme example of a state machine controlling all the objects in a domain. Controller objects, usually singletons, result in systems that fail to exploit the concurrency in the domain�a disastrous result in these days of distributed systems.


Consider what happens when we extend the online bookstore to allow customers to remove items from a cart and to change the quantity of individual selections. When we add these signals to the shopping cart, we create a complex nest of states and transitions. The signals addSelection, removeSelection, changeQuantity, cancelCart, and checkOut can each be accepted in most of the states of the shopping cart, as shown in Figure 14.2.


Figure 14.2. Messy Shopping Cart



The cart now exhibits a typical characteristic of complex state machines. Like the single-instance controller, it is a single instance (of the cart) trying to manage multiple instances (of the selections). The solution is to factor out the management of a single selection into a separate Selection statechart diagram. Items are added to the cart by creating instances of Selection; the cart receives only cartUpdated events and does not need to deal with the management of the selection instances. This results in a greatly simplified cart model, as shown in Figure 14.3.


Figure 14.3. Cleaned-Up Cart



In summary, a domain with good control partitioning exhibits three key characteristics:



  • Behavior is partitioned among the classes in a domain: One class does not do all the work, leaving other classes simply to respond to signals and be updated.


  • Behavior can be (re)factored to simplify behavior so long as the factored behavior describes some concept in the domain.


  • Behavior is partitioned among objects: We generally build state machines to represent the behavior of single objects, not of the class as a whole. (Assigners are sometimes an exception.)









    I l@ve RuBoard



    No comments: