。混杂的方法 是包含 各种功能的大型方法,涉及问题领域的各个方面。根据定义,代码库中达到 300 行的方法就是混杂的方法。这么大的方法怎么可能是内聚的呢 ?混杂的方法是阻碍重构、测试和紧急设计的主要因素之一。
清单 1 不包含任何特别复杂的东西。但是,它也不包含明显的可重用代码。尽管它相当短,但是仍然应该重构。组合方法模式指出,每个 方法应该只做一件事,这个方法违反了此规则。我认为,在 Java 项目中任何超过 10 行代码的方法都应该考虑重构,因为它很可能做多件事 。因此,我将根据组合方法模式重构这个方法,看看是否可以分离出原子性部分。重构的版本见清单 2:
清单 2. 重构的 populate() 方法
public void populate() throws Exception {
Connection c = null;
try {
c = getDatabaseConnection();
ResultSet rs = createResultSet(c);
while (rs.next())
addPartToListFromResultSet(rs);
} finally {
c.close();
}
}
private ResultSet createResultSet(Connection c)
throws SQLException {
return c.createStatement().
executeQuery(SQL_SELECT_PARTS);
}
private Connection getDatabaseConnection()
throws ClassNotFoundException, SQLException {
Connection c;
Class.forName(DRIVER_CLASS);
c = DriverManager.getConnection(DB_URL,
"webuser", "webpass");
return c;
}
private void addPartToListFromResultSet(ResultSet rs)
throws SQLException {
Part p = new Part();
p.setName(rs.getString("name"));
p.setBrand(rs.getString("brand"));
p.setRetailPrice(rs.getDouble("retail_price"));
partList.add(p);
}
populate() 方法现在短多了,看起来像是它需要执行的任务的大纲,任务的实现都放在私有方法中。把所有原子性部分分离出来之后,就 可以看出我实际上拥有哪些资产了。注意,getDatabaseConnection() 方法没有对 parts 做任何操作 — 它只提供通用的数据库连接功能。这 说明这个方法不应该放在这个类中,所以我要把它重构到 PartDb 类的父类 BoundaryBase 中。
清单 2 中是否还有其他方法是通用的,能够放到父类中?createResultSet() 方法看起来相当通用,但是它包含 parts 的链接,即 SQL_SELECT_PARTS 常量。如果能够迫使子类 (PartDb) 把这个 SQL 字符串的值告诉父类,就可以把这个方法提升到父类中。这正是抽象方法 的作用。因此,我把 createResultSet() 提升到 BoundaryBase 类中,并声明一个名为 getSqlForEntity() 的抽象方法,见清单 3:
清单 3. 目前的 BoundaryBase 类
abstract public class BoundaryBase {
private static final String DRIVER_CLASS =
"com.mysql.jdbc.Driver";
private static final String DB_URL =
"jdbc:mysql://localhost/orderentry";
protected Connection getDatabaseConnection() throws ClassNotFoundException,
SQLException {
Connection c;
Class.forName(DRIVER_CLASS);
c = DriverManager.getConnection(DB_URL, "webuser", "webpass");
return c;
}
abstract protected String getSqlForEntity();
protected ResultSet createResultSet(C
|