类从变量列表开始,公共静态常量先出现,私有静态变量,私有实体变量。很少有公共变量。
某个公共函数的私有工具函数紧随在公共函数之后,符合自顶向下原则。
封装
受保护变量或工具函数,好让测试能够访问。若同一程序包内的某个测试需要调用一个函数或变量,一般设定会受保护或在整个程序包内可访问,优先private,其次考虑protected。
函数,通过代码行衡量大小;类,通过权责衡量大小,应该尽可能短小。
类的名称应当描述其权责,命名是帮助判断类的长度的第一个手段,如果无法为某个类命以精确的名称,类名太含混,那类就拥有过多权责,太长。
类不应当由含义过于模糊的词
类或模块有且仅有一条加以修改的理由,需要认识并创建出更好的抽象。
大多数人脑力优先,只能把更多精力放在代码能工作上,而不是保持代码有组织和整洁上。
类应该只有少量实体变量,类中的每个方法都应该操作一个或多个这种变量。
如果一个类中的每个变量都被每个方法所使用,具有最大的内聚性。
当增加新语句或改动单个语句都要修改,这本质已经违反了只有一个修改理由的SRP原则。
存在改进空间,借助继承和组合使得公有行为成为顶层,子类针对不同场景进行覆盖,这样新增功能也不会影响旧代码。
隔离修改
具体类包含实现细节,抽象类只呈现概念,依赖于具体细节的客户类。
当细节改变时,就会有风险,可以借助接口和抽象类来隔离这些细节带来的影响。
案例:构建一个依赖于外部的TokyoStockExchange
API的Portfolio
类,代表投资组合的价值,测试用例受到价值查询的连带影响。
与其设计直接依赖于 TokyoStockExchange
的 Portfolio
类,不如创建 StockExchange
接口,其中只声明一个方法,不依赖具体细节,而依赖于接口,这种抽象隔离了所有特定细节。
public interface StockExchange {
Money currentPrice(String symbol);
}
public class Portfolio {
private StockExchange exchange;
public Portfolio(StockExchange exchange) {
this.exchange = exchange;
}
}
//测试
public class PortfolioTest {
private FixedStockExchangeStub exchange;
private Portfolio portfolio;
@Before
protected void setUp() throws Exception {
exchange = new FixedStockExchangeStub();
exchange.fix("MSFT", 100);
portfolio = new Portfolio(exchange);
}
@Test
public void GivenFiveMSFTTotalShouldBe500() throws Exception {
portfolio.add(5, "MSFT");
Assert.assertEquals(500, portfolio.value());
}
}