Divergent Change


Divergent Change

Symptoms

  • You find yourself changing the same class for different reasons. (For contrast, see Shotgun Surgery, the next smell we look at.)

Causes

The class picks up more responsibilities as it evolves, with no one noticing that two different types of decisions are involved. (Recall in Chapter 6 we talked about Parnas's dictum that a module should have only one secret.)

What to Do

  • If the class both finds an object and does something with it, let the caller find the object and pass it in, or let the class return a value that the caller uses.

  • Extract Class to pull out separate classes for the separate decisions.

  • If several classes are sharing the same type of decisions, you may be able to consolidate those new classes (e.g., by Extract Superclass or Extract Subclass ). In the limit, these classes can form a layer (e.g., a persistence layer).

Payoff

Improves communication (by expressing intent better). Improves robustness to future changes.

Contraindications

None identified.

Exercise 39 CsvWriter.

Consider this code to write Comma-Separated Value ( CSV ) files. (Online at http://www.xp123.com/rwb )

CsvWriter.java

 public class CsvWriter {     public CsvWriter() {}     public void write(String[][] lines) {         for (int i = 0; i < lines.length; i++)             writeLine(lines[i]);     }     private void writeLine(String[] fields) {         if (fields.length == 0)             System.out.println();         else {             writeField(fields[0]);             for (int i = 1; i < fields.length; i++) {                 System.out.print(",");                 writeField(fields[i]);             }             System.out.println();         }     }     private void writeField(String field) {         if (field.indexOf(',') != -1  field.indexOf('\"') != -1)             writeQuoted(field);         else             System.out.print(field);     }     private void writeQuoted(String field) {         System.out.print('\"');         for (int i = 0; i < field.length(); i++) {             char c = field.charAt(i);             if (c == '\"')                 System.out.print("\"\"");             else                 System.out.print(c);         }         System.out.print('\"');     } } 

CsvWriterTest.java (A Manual Test)

 import junit.framework.TestCase; public class CsvWriterTest extends TestCase {     public CsvWriterTest (String name) {         super(name);     }     public void testWriter() {         CsvWriter writer = new CsvWriter();         String[] [] lines = new String[] [] {   new String[] {},   new String[] {"only one field"},   new String[] {"two", "fields"},   new String[] {"", "contents", "several words included"},   new String[] {",", "embedded , commas, included", "trailing comma,"},   new String[] {"\"", "embedded \" quotes",       "multiple \"\"\" quotes\"\""},   new String[] {"mixed commas, and \"quotes\"", "simple field"}         };         // Expected:         //                      -- (empty line)         // only one field         // two,fields         // ,contents,several words included         // ",","embedded , commas, included","trailing comma,"         // """","embedded "" quotes","multiple """""" quotes"""""         // "mixed commas, and ""quotes""",simple field         writer.write(lines);     } } 
  1. How is this code an example of divergent change? (What decisions does it embody?)

  2. Modify this code to write to a stream passed in as an argument.

  3. Starting from the original code, modify the functions to return a string value corresponding to what the functions would have written.

  4. Which version seems better and why? Which is easier to test?

See Appendix A for solutions.


Exercise 40 CheckingAccount.

Consider these class fragments :

 public class CheckingAccount {    public int balance() {...}    public void add(Transaction transaction) {...} } public class Transaction {    public int cost() {...} } 
  1. What decisions are embedded in these classes?

  2. Extract a simple Money class.

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