Data Class


Symptoms

  • The class consists only of public data members , or of simple getting and setting methods . This lets clients depend on the mutability and representation of the class.

Causes

It's common for classes to begin like this: You realize that some data is part of an independent object, so you extract it. But objects are about the commonality of behavior , and these objects aren't developed enough as yet to have much behavior.

What to Do

  1. Encapsulate Field to block direct access to the fields (allowing access only through getters and setters).

  2. Remove Setting Methods for any methods you can.

  3. Encapsulate Collection to remove direct access to any collection-type fields.

  4. Look at each client of the object. Almost invariably, you'll find clients accessing the fields and manipulating the results when the class could do it for them. (This is often a source of duplication, because many callers will tend to do the same things with the data.) Use Extract Method on the client to pull out the class- related code, then Move Method to put it over on the class.

  5. After doing this awhile, you may find that you have several similar methods on the class. Use refactorings such as Rename Method, Extract Method, Add Parameter, or Remove Parameter to harmonize signatures and remove duplication.

  6. Most access to the fields shouldn't be needed anymore because the moved methods cover the real use. So use Hide Method to eliminate access to the getters and setters. (You may decide to keep them with private access and have all internal access go through them.)

Payoff

Improves communication. May expose duplication (as you'll often find clients manipulating the fields in similar ways).

Contraindications

There are times when the encapsulation of fields can have a performance cost. For example, consider a point with x and y coordinates. The interface (probably) isn't going to change, and people may deal with lots of points. So, in Java, the Point class makes its fields public. (This saves the cost of a procedure call for each access.)

Some persistence mechanisms rely on reflection or getter/setter methods to see fields to determine what data should be loaded or stored. For these classes, you may never be able to eliminate their data class nature. If I'm stuck with this, I try to treat these classes as Mementos (see Gamma's Design Patterns ). Sometimes I'll use another class as a layer above these persistence-only classes; that new class can benefit from all the changes described above, and it will hide the low-level classes.

EXERCISE 28 Library Classes.

Compare these library classes. What do they have in common?

 java.awt.Event java.awt.GridBagConstraints java.awt.Insets java.awt.Point java.awt.Polygon java.awt.Rectangle 

See Appendix A for solutions.

EXERCISE 29 Color and Date.

The classes java.awt.Color and java.util.Date are examples of classes encapsulated such that access to members is only through methods.

  1. Propose at least two internal representations for each class.

  2. How does having no direct access to members promote the ability of a class to be immutable?

See Appendix A for solutions.

EXERCISE 30 Proper Names . (Challenging).
  1. Clean up this Data Class. (Online at www.xp123.com/rwb )

Person.java

 public class Person {     public String last;     public String first;     public String middle;     public Person(String last, String first, String middle) {         this.last = last;         this.first = first;         this.middle = middle;     } } 

PersonClient.java

 // The clients are in one file for convenience; // imagine them as non-test methods in separate client classes. import junit.framework.TestCase; import java.io.* public class PersonClient extends TestCase {     public PersonClient(String name) {super(name);}     public void client1(Writer out, Person person) throws IOException {         out.write(person.first);         out.write(" ");         if (person.middle != null) {             out.write(person.middle);             out.write(" ");         }         out.write(person.last);     }     public String client2(Person person) {         String result = person.last + ", " + person.first;         if (person.middle != null)             result += " " + person.middle;         return result;     }     public void client3(Writer out, Person person) throws IOException {         out.write(person.last);         out.write(", ");         out.write(person.first);         if (person.middle != null) {             out.write(" ");             out.write(person.middle);         }     }     public String client4(Person person) {         return person.last + ", " +                person.first +                ((person.middle == null) ? "" : " " + person.middle);     }     public void testClients() throws IOException {         Person bobSmith = new Person("Smith", "Bob", null);         Person jennyJJones = new Person("Jones", "Jenny", "J");         StringWriter out = new StringWriter();         client1(out, bobSmith);         assertEquals("Bob Smith", out.toString());         out = new StringWriter();         client1(out, jennyJJones);         assertEquals("Jenny J Jones", out.toString());         assertEquals("Smith, Bob", client2(bobSmith));         assertEquals("Jones, Jenny J", client2(jennyJJones));         out = new StringWriter();         client3(out, bobSmith);         assertEquals("Smith, Bob", out.toString());         out = new StringWriter();         client3(out, jennyJJones);         assertEquals("Jones, Jenny J", out.toString());         assertEquals("Smith, Bob", client4(bobSmith));         assertEquals("Jones, Jenny J", client4(jennyJJones));     } } 
  1. There's a new requirement to support people with only one name (say, Cher or Madonna) or with several last names (Oscar de los Santos). Compare the difficulty of this change before and after your refactoring in the previous part.

See Appendix A for solutions.




Refactoring Workbook
Refactoring Workbook
ISBN: 0321109295
EAN: 2147483647
Year: 2003
Pages: 146

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