第八章 边界
有时候我们会购买第三方包和使用开源代码或者是其他团队开发的组件系统。我们应该保持软件边界整洁的实践手段和技巧。
8.1 使用第三方代码
在接口提供者和使用者之间,存在与生俱来的张力。第三方程序包和框架提供者追求普适性,这样就能在多个环境中工作,吸引广泛的用户。而使用者则想要集中满足特定需求的接口。这种张力会导致系统边界上出现问题。
Map很灵活,我们我们需要一个包含了Sensor类对象的Map映射图:
Map sensors = new HashMap();
当代码的其他部分需要访问这些sensor,会有这行代码:
Sensor s = (Sensor) sensor.get(sensorId);
这行代码承担了从Map中获取对象并将他转化成正确的类型。这样的代码就不简洁了。
有了泛型之后:
Map sensors = new HashMap<>();
Sensor s = sensors.get(sensorId);
不过,Map提供了抽出所需、所愿的功能问题,仍未得到解决。
在系统中不受限制的传递Map,当Map的接口被修改时,也有许多地方需要修改。
使用Map的更整洁的方式大致如下,用户不必关心是否使用了泛型
8.2 浏览和学习边界
同时做这两件事难上加难。如果我们采 用不同的做法呢?不要在生产代码中试验新东西,而是编写测试来遍览和理解第三方代码。 Jim newkirk 把这叫做学习性测试。
8.3 学习log4j
就是边使用,边学习,然后想办法抽象。
8.4 学习性测试的好处不只是免费
学习性的测试毫无成本。无论如何我们都得学习要使用的API,而编写测试则是获得这些知识的容易而不会影响其他工作的途径。学习性的测试是一种精确试验,帮助我们增进对API的理解。
学习性测试不光免费,还在投资上有正面的回报。当第三方程序包发布了新版本,我们 可以运行学习性测试,看看程序包的行为有没有改变。并且保证是与我们系统是兼容。
8.5 使用尚不存在的代码
还有另一种边界,那种将已知和未知分隔开的边界。在代码中总有许多地方是我们的知识未及之处。有时,边界那边就是未知的(至少目前未知)。有时,我们并不往边界那边看过去。
在无线系统工作的时候,有个子系统Transmitter (发送机)。我们对他不了解,而且他们的开发者还没有将接口定义出来,为了不被这种事情阻碍到,我们就要做一些事情。我们给它写了个名为transmit 的方法,获取频率参数和数据流。这就是我们希望得到的接口。
8.6 整洁的边界
边界上会发生有趣的事。改动是其中之一。有良好的软件设计,无需巨大投入和重写即可进行修改。在使用我们控制不了的代码时,必须加倍小心保护投资,确保未来的修改不至于代价太大
边界上的代码需要清晰的分割和定义了期望的测试。应该避免我们的代码过多地了解第三方代码中的特定信息。依靠你能控制的东西,好过依靠你控制不了的东西,免得日后受它控制。