代码整洁之道-读书笔记之边界
1. 使用第三方代码
在接口提供者和使用者之间,存在与生俱来的张力。第三方程序包和框架提供者追求普适性,这样就能在多个环境中工作,吸引广泛的用户。二使用者则想要集中满足特定需求的接口。这种张力会导致系统边界上出现问题。
不建议服务和服务之间、接口和接口之间通过Map传递
2.浏览和学习边界
第三方代码帮助我们在更少时间内发布更丰富的功能。在利用第三方程序包时,该从何处入手呢?我们没有测试第三方代码的职责,但为要使用的第三方代码编写测试,可能最符合我们的利益。
设想我们对第三方代码库的使用方法并不清楚。我们可能会花上一两天(或者更多)的时间阅读文章,决定如何使用。然后,我们编写使用第三方代码的代码,看看是否如我们所愿的公工作。我们会陷入长时间的调试,找出在我们或他们代码种的缺陷。这可不是什么稀罕事。
学习第三方代码很难,整合第三方代码也很难,同时做着两件事难上加难。如果我们采用不同的做法呢?不要在成产代码种试验新东西,而是编写测试来便览和理解第三方代码。Jim Newkirk把这叫做学习性测试。
在学习性测试中,我们就像在应用中那样调用我们第三方代码,我们基本上时在通过核对试验来检测自己对那个API的理解程度。测试聚焦于我们想从API得到的东西。
3.学习log4j
3.1日志等级
1、TRACE 在线调试
默认情况下,即不打印到终端也不输出到文件。对程序的运行效率几乎不产生影响。
2、DEBUG 终端查看、在线调试
默认情况下,打印到终端输出,但是不会归档到日志文件。因此,一般用于开发者在程序当前启动窗口上,查看日志的流水信息。
3、INFO 报告程序进度和状态信息
一般这种情况都是一次性的,不会大量反复输出。
4、WARNING 警告信息
程序处理中遇到非法数据或者某种可能的错误。该错误是一过性的、可恢复的,不会影响程序的继续运行,程序仍处在正常状态。
5、ERROR 状态错误
该错误发生后程序仍然可以运行,但是极有可能运行在某种非正常的状态下,导致无法完成全部既定的功能。
6、FATAL 致命错误
表明程序遇到了致命的错误,必须马上终止运行。
Log4j建议只使用四个级别,优先级从高到低分别是
ERROR > WARN > INFO > DEBUG
3.2书本内容
比如,我们想使用Apache log4j包来代替自定义的日志代码。我们下载了log4j,打开介绍文档页,无需看太久,就编写了第一个测试用例,希望他能在控制台打印输出“hello”字样。
@Test
public void testLogCreate(){
log.info("info");
}
运行上述代码, logger发生了一个错误,告诉我们需要用Appender。在多读一点文档,我们发现有个ConsoleAppender。于是我们创建了一个ConsoleAppender,再看是否能解开控制台输出日志的秘诀。
@Test
public void testLogAddAppender(){
Logger logger = Logger.getLogger("MyLogger");
logger.removeAllAppenders();
logger.addAppender(new ConsoleAppender(
new PatternLayout("%p %t %m%n"),
ConsoleApender.SYSTEM_OUT)
);
Logger.info("hello");
}
这回行了,”hello”字样的日志信息出现在控制台上!必须告知ConsoleAppender,让它往控制台写字,看起来有点奇怪。
很有趣,当我们移除ConsoleAppender.SystemOut参数时,那个“hello”字样仍然输出到屏幕上。但如果取走PatternLayout,就会出现关于没有输出流的错误信息,这实在太古怪了。
再仔细看看文档,我们看到默认的ConsoleAppender构造器时”未配置”的,这看起来并不明显或没什么用,反而像是log4j的一个缺陷,或者至少时前后不太一致。
在搜索、阅读、测试,最终我们的带代码如下。
public class LogTest {
Private Logger logger;
@Before
pubolic void initialize() {
logger = Logger.getLogger("logger");
logger.removeAllAppenders();
logger.getRootLogger().removeAllAppenders();
}
@Test
public void basicLogger() {
BasicConfigurator.configure();
logger.info("basicLogger");
}
@Test
public void addAppenderWithStream() {
logger.appAppender(new ConsoleAppender(
new PatternLayout("%p %t %m%n"),
ConsoleApender.SYSTEM_OUT
));
logger.info("addAppenderWithStream");
}
@Test
public void addAppenderWithoutStream() {
logger.addAppender(new ConsoleAppender(
new PatternLayout("%p %t %m%n")
));
logger.info("addAppenderWithoutStream");
}
}
现在我们知道如何初始化一个简单的控制台日志器,也能把之这些知识封装到自己的日志类中,好将应用程序的其他部分与log4j的边界接口隔离开来。
4. 学习性测试的好处不只是免费
学习性测试:用以表述在对第三方接口或资源包学习的过程中,通过本地编写测试来遍历我们需要用到的功能,并以此作为后续自身项目质量保证一环的软件编程行为
好处:当第三方资源进行版本升级的时候,可以通过测试代码很好的展示出,版本升级带来的问题,并且及时修复
5. 使用尚不存在的代码
在开发过程中,需要与第三方交互,但是接口还没有实现,这个时候我们可以mock接口的入参和出参还有接口请求方式,从而不影响自己以及其他人的开发进度,当接口开发完成,再修改成真实的接口
我们和第三方交互,mock第三方接口
前端和我们交互,给前端提供mock接口
6. 整洁的边界
有良好的软件设计,无需巨大投入和重写即可进行修改。在使用我们控制不了的代码时,必须加倍小心保护投资,确保未来的修改不至于代价太大。
控制你能控制的,好过依赖你控制不了的,避免日后受它控制