Refactoring


Both CourseSessionTest and RosterReporterTest require the createDate utility method. The code in createDate has nothing to do with course sessions or roster reports; it deals solely with constructing date objects. Including minor utility methods in classes is a mild violation of the Single-Responsibility Principle. You can tolerate small doses of duplication, but in doing so you quickly open the door to excessive, costly duplication in your system. In a larger system, there might be half a dozen methods that construct dates, all with pretty much the same code.

Here the duplication is obvious, since you directly created (and hopefully noted) it. An alternate approach is to not even let the duplication occur: As soon as you recognize that you might be introducing duplicate code, do the necessary refactoring first to stave off the potential duplication.

You will create a new test class and production class. You must update AllTests to reference the new test class. The code for all three follows.

 // DateUtilTest.java package studentinfo; import java.util.*; import junit.framework.*; public class DateUtilTest extends TestCase {    public void testCreateDate() {       Date date = new DateUtil().createDate(2000, 1, 1);       Calendar calendar = new GregorianCalendar();       calendar.setTime(date);       assertEquals(2000, calendar.get(Calendar.YEAR));       assertEquals(Calendar.JANUARY, calendar.get(Calendar.MONTH));       assertEquals(1, calendar.get(Calendar.DAY_OF_MONTH));    } } // DateUtil.java package studentinfo; import java.util.*; class DateUtil {    Date createDate(int year, int month, int date) {       GregorianCalendar calendar = new GregorianCalendar();       calendar.clear();       calendar.set(Calendar.YEAR, year);       calendar.set(Calendar.MONTH, month - 1);       calendar.set(Calendar.DAY_OF_MONTH, date);       return calendar.getTime();    } } // AllTests.java package studentinfo; import junit.framework.TestSuite; public class AllTests {    public static TestSuite suite() {       TestSuite suite = new TestSuite();       suite.addTestSuite(StudentTest.class);       suite.addTestSuite(CourseSessionTest.class);       suite.addTestSuite(RosterReporterTest.class);       suite.addTestSuite(DateUtilTest.class);       return suite;    } } 

Previously, no tests existed for the createDate method, since it was only a utility for use in test classes themselves. When extracting code from one class to a new class, you should always move along any tests that exist into the corresponding new test class. When tests do not exist, you should expend the time to create them. This will maintain the sustainability of your system.

Now that you have created and tested the DateUtil class, you want to update your code to refer to it. At the same time, you want to remove the createDate method from both CourseSessionTest and RosterReporterTest. One solid approach is to remove the createDate method from both places and recompile. The compiler will tell you precisely which lines of code refer to the nonexistent createDate method.

Use the compiler to help you refactor code.


Change these lines.

 // CourseSessionTest package studentinfo; import junit.framework.TestCase; import java.util.*; public class CourseSessionTest extends TestCase {    ...    public void setUp() {       startDate = new DateUtil().createDate(2003, 1, 6);       session = new CourseSession("ENGL", "101", startDate);    }    ...    public void testCourseDates() {       Date sixteenWeeksOut = new DateUtil().createDate(2003, 4, 25);       assertEquals(sixteenWeeksOut, session.getEndDate());    } } // RosterReporterTest.java package studentinfo; import junit.framework.TestCase; public class RosterReporterTest extends TestCase {    public void testRosterReport() {       CourseSession session =          new CourseSession("ENGL", "101",              new DateUtil().createDate(2003, 1, 6));       ...    } } 

In order to use the createDate utility method, you must construct a DateUtil object each time. In the case of CourseSession test, you construct a DateUtil object twicea prime candidate for refactoring. You could create an instance variable to hold onto a DateUtil instance. A better solution, however, is to convert the DateUtil to a static methoda method you can call without creating instances of DateUtil. You will learn how to do this in Lesson 4.



Agile Java. Crafting Code with Test-Driven Development
Agile Javaв„ў: Crafting Code with Test-Driven Development
ISBN: 0131482394
EAN: 2147483647
Year: 2003
Pages: 391
Authors: Jeff Langr

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