Refactoring


The getComponent method calls require casts. For example:

 JTextField numberField =    (JTextField)Util.getComponent(panel, NUMBER_FIELD_NAME); 

Since you must retrieve two text fields from the panel, you have two lines of code with the same cast. This is a form of duplication that you can eliminate, using convenience methods that both eliminate the cast and make the code clearer.

The separate utility class Util contains the getComponent method. However, it is perhaps more appropriate for CoursesPanel to have this responsibility, since a panel is a container of components.

The following listing shows a highly refactored CoursesPanelTest. Some of the changes to CoursesPanelTest will necessitate changes in CoursesPanelsee the listing after this one.

 package sis.ui; import junit.framework.*; import javax.swing.*; import java.awt.*; import static sis.ui.CoursesPanel.*; public class CoursesPanelTest extends TestCase {    private CoursesPanel panel;    protected void setUp() {       panel = new CoursesPanel();    }    public void testCreate() {       assertLabelText(COURSES_LABEL_NAME, COURSES_LABEL_TEXT);       assertEmptyList(COURSES_LIST_NAME);       assertButtonText(ADD_BUTTON_NAME, ADD_BUTTON_TEXT);       assertLabelText(DEPARTMENT_LABEL_NAME, DEPARTMENT_LABEL_TEXT);       assertEmptyField(DEPARTMENT_FIELD_NAME);       assertLabelText(NUMBER_LABEL_NAME, NUMBER_LABEL_TEXT);       assertEmptyField(NUMBER_FIELD_NAME);    }    private void assertLabelText(String name, String text) {       JLabel label = panel.getLabel(name);       assertEquals(text, label.getText());    }    private void assertEmptyField(String name) {       JTextField field = panel.getField(name);       assertEquals("", field.getText());    }    private void assertEmptyList(String name) {       JList list = panel.getList(name);       assertEquals(0, list.getModel().getSize());    }    private void assertButtonText(String name, String text) {       JButton button = panel.getButton(name);       assertEquals(text, button.getText());    } } 

While some of these refactorings eliminate duplication, technically not all of them do. However, those refactorings that do not eliminate duplication help improve readability. First, even though only one list needs to be verified, creating assertEmptyList more clearly states the intent. Second, extracting assertButtonText allows the entire body of testCreate to contain singleline, simple, consistently phrased assertion statements.

Each of the new assertion methods contains two implicit tests. First, if no component with the given name exists within the panel, a NullPointerException will be thrown, failing the test. Second, if the component is not of the expected type, a ClassCastException will be thrown, also failing the test. If this implicitness bothers you, feel free to add additional assertions (e.g. assertNotNull), but I don't view them as necessary.

The new assertion methods are very general purpose. When (or if) you add a second panel to the SIS application, you can refactor the assertion methods to a common test utility class. You might choose to move them to a junit.framework.TestCase subclass that all panel test classes inherit.

In most systems, Swing code and associated test code is excessive and repetitive. Take the time up front to do these refactorings. You will significantly minimize the amount of redundancy and overall code in your system.

You can refactor component creation in CoursesPanel in a similar manner. The following listing shows new component creation methods in addition to the get methods required by the test.

 package sis.ui; import javax.swing.*; import java.awt.*; public class CoursesPanel extends JPanel {    static final String NAME = "coursesPanel";    static final String COURSES_LABEL_TEXT = "Courses";    static final String COURSES_LABEL_NAME = "coursesLabel";    ...    private void createLayout() {       JLabel coursesLabel =          createLabel(COURSES_LABEL_NAME, COURSES_LABEL_TEXT);       JList coursesList = createList(COURSES_LIST_NAME);       JButton addButton =          createButton(ADD_BUTTON_NAME, ADD_BUTTON_TEXT);       int columns = 20;       JLabel departmentLabel =          createLabel(DEPARTMENT_LABEL_NAME, DEPARTMENT_LABEL_TEXT);       JTextField departmentField =          createField(DEPARTMENT_FIELD_NAME, columns);       JLabel numberLabel =          createLabel(NUMBER_LABEL_NAME, NUMBER_LABEL_TEXT);       JTextField numberField =          createField(NUMBER_FIELD_NAME, columns);       add(coursesLabel);       add(coursesList);       add(addButton);       add(departmentLabel);       add(departmentField);       add(numberLabel);       add(numberField);    }    private JLabel createLabel(String name, String text) {       JLabel label = new JLabel(text);       label.setName(name);       return label;    }    private JList createList(String name) {       JList list = new JList();       list.setName(name);       return list;    }    private JButton createButton(String name, String text) {       JButton button = new JButton(text);       button.setName(name);       return button;    }    private JTextField createField(String name, int columns) {       JTextField field = new JTextField(columns);       field.setName(name);       return field;    }    JLabel getLabel(String name) {       return (JLabel)Util.getComponent(this, name);    }    JList getList(String name) {       return (JList)Util.getComponent(this, name);    }    JButton getButton(String name) {       return (JButton)Util.getComponent(this, name);    }    JTextField getField(String name) {       return (JTextField)Util.getComponent(this, name);    } } 



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