Refactoring from Class Diagrams


Just two refactoring types are covered in this section: Extract Interface and Implement Abstract Class, which we'll demonstrate using a C# Class Diagram.

Extract Interface

Interfaces enable you to apply polymorphism across hierarchies, namespaces, assemblies, and programming languages. They also enable you to define sets of abstract (that is, not implemented) properties, methods, and events that may be implemented by other types in compliance with a well-defined contract. Sometimes you will devise interfaces up-front, but often the need for an interface will occur to you as you add members to a class and realize that those members have usefulness beyond that one class. In such cases, you can extract those members into an interface retrospectively using the Extract Interface refactoring.

As a concrete example, consider the following scenario: Suppose that in a stockbroking application you conceive a class named StockPurchase, the purpose of which is to hold a record of the number of shares purchased by a customer for a particular stock. That class would have two private members fields, mNumberOfSharesBought and mStockSymbol, each exposed by similarly named properties NumberOfSharesBought and StockSymbol. You might also decide to expose the number of shares involved in the purchase via a shorter-named property NumberOfShares. In addition, because this application will be subject to regulatory scrutiny, you would probably add an audit method to the class, thereby enabling details of that deal to be persisted in an audit trail.

Note

If you read Part 1 of this book on Team Architect, you might be experiencing some dj vu now because we used a stockbroking system as the running example in that section. Though we're returning to that theme here, there is no mandatory link between the two sections and you can treat everything you read here as relevant in its own right.

Besides stock purchases, you would also want to handle stock sales by devising a StockSale class, and you would correctly deduce that both the StockPurchase and StockSale classes should include a NumberOfShares and a StockSymbol. That commonality could be encoded into an abstract class (as you did in Chapter 5) or as an interface (as you will do here).

Having already devised the common properties as members of the StockPurchase class, you'll be pleased to know about a shortcut you can use to make those members available to other classes via an interface. Just right-click the class and choose Refactor image from book Extract Interface to launch the Extract Interface dialog, shown in Figure 11-1.

image from book
Figure 11-1

Using that dialog, you can create a new interface named IStockDeal, and select the NumberOfShares and StockSymbol properties for extraction into the interface.

You might be wondering why we haven't recommended you extract the audit method into that interface too. After all, you would want to audit sales as well as purchases. However, you might want auditing to be applied more broadly, not limited to stock sales and purchases. Maybe you would be required to audit changes to the state of any object in your application — in which case it makes sense to extract the audit method separately into an IAudit interface, to be implemented by every class.

If you take this discussion to its logical conclusion, the result would be something like what is shown in Figure 11-2.

image from book
Figure 11-2

  • The IStockDeal interface, with NumberOfShares and StockSymbol properties, was created automatically by the refactoring, as was the IAudit interface, with its audit method.

  • The two extracted interfaces are shown emanating as a lollipop (interface) shape from the StockPurchase class.

  • By adding a StockSale class to the diagram and drawing inheritance relationships between that class and the two interfaces, respectively, the class is populated automatically with the members required by the interfaces.

  • By adding a Customer class to the diagram and drawing an inheritance relationship between it and the IAudit interface, we have shown that the IAudit interface may be applicable to a wider selection of classes (possibly every class), whereas the IStockDeal interface has a narrower appeal.

Note

An extracted interface specifies only the member signatures, not their implementations, which is why private member mStockSymbol has not been copied automatically into the StockSale class in support of the StockSymbol property.

The following listing shows the result in code of the actions taken on the Class Diagram (note the inherited interfaces and auto-generated regions for properties and methods implementations):

     public class StockSale : Refactoring.IStockDeal, Refactoring.IAudit     {           #region IStockDeal Members           public int NumberOfShares           {            get            {              throw new Exception("The method or operation is not implemented.");            }            set            {              throw new Exception("The method or operation is not implemented.");            }          }          public String StockSymbol           {            get             {               throw new Exception("The method or operation is not implemented.");             }            set             {              throw new Exception("The method or operation is not implemented.");             }           }           #endregion           #region IAudit Members           public void audit()           {           throw new Exception("The method or operation is not implemented.");           }           #endregion     } 

Although we used the Class Designer for demonstration, it isn't necessary to initiate this refactoring type from there. You can also select code in the code editor, right-click, and choose Refactor image from book Extract Interface.

Implement Abstract Class

In the previous example we used an interface (IStockDeal) to factor out the common behavior of different kinds of deals, whereas in Chapter 5 we used an abstract base class to achieve the same effect.

Assuming you took the Abstract Class route, you might conceive the abstract class first and then show one or more concrete classes deriving from it, as shown in Figure 11-3.

image from book
Figure 11-3

Given a diagram like the one shown, you can right-click one of the derived classes — StockPurchaseConcreteClass or StockSaleConcreteClass — and choose IntelliSense image from book Implement Abstract Class to copy the members from the abstract class to the (derived) concrete class.

Note that for the refactoring to take effect the members of the base class, as well as the base class itself, must all be declared as Abstract.

Note

You're no doubt wondering why that refactoring type was located under the IntelliSense submenu, rather than the Refactor submenu. In fact, in the early betas of Visual Studio 2005, it did sit as a refactoring type, until Microsoft decided that because it does not truly "refactor" any code, it should reside under a different menu. We still think of it as a kind of refactoring, a counterpart of Extract Interface, and — crucially for this section — one that you can invoke directly from a class diagram.



Professional Visual Studio 2005 Team System
Professional Visual Studio 2005 Team System (Programmer to Programmer)
ISBN: 0764584367
EAN: 2147483647
Year: N/A
Pages: 220

flylib.com © 2008-2017.
If you may any questions please contact us: flylib@qtcs.net