错误处理(异常处理)
异常处理是程序必须做的事情之一,但是如果因为它搞乱了代码逻辑<br>让读者无法看明白代码所做的事情,就是错误的做法
使用异常而非错误码
该代码是单条件,不满足条件无程序执行,才适用于书中所说的修改方案
整理后的
打包异常
当需要捕获多个第三方API的异常并进行不同的逻辑操作时,可以将处理异常的过程新建一个打包类,<br>不仅代码更简洁,而且减少了对它的依赖
特例模式
创建一个类或配置一个对象,用来代替处理个别异常的行为。业务代码就不用进行异常处理了
别返回null
用空的集合返回,减少多做空值检查判断
水哥的selectList()查询采用了该方式
别传递null值
单元测试
测试驱动开发
TDD三定律(待定)
在编写不同通过的单元测试前,不可编写生产代码
只可编写刚好无法通过的单元测试,不能编译也算不通过
只可编写刚好足以通过当前失败测试的生产代码
测试代码和生产代码一样重要
好的全套自动化单元测试可以确保修改生产代码后的程序正确性
单元测试让你的代码可拓展、可维护、可复用
减少对修改代码的担忧,测试覆盖率越高,就越不担心修改
整洁的测试
每个测试一个概念、一个断言
规则FIRST
快速Fast
独立Independent
可重复Repeatable
自足验证Self-Validating
及时Timely
测试与生产的双重标准
例如字符串的拼接在测试中可以直接用+,而不用StringBuilder或StringBuffer,因为不用担心内存资源问题
类
类应该从一组变量列表开始,如果有公共静态常量,应该先出现,然后是私有静态变量,以及私有实体变量
类应该短小
类的名称应当描述其职责
类名越含糊,则说明该类的职责过多
单一权责原则SRP
依赖倒置原则DIP
类应当依赖于抽象而不是依赖于具体细节
内聚
内聚性高,意味着类中的方法和变量相互依赖、互相结合成一个逻辑整体
系统
将系统的构造与使用分开
抽象工厂模式让应用自行控制何时创建对象,将构造的细节与应用程序代码隔离
依赖注入DI
控制反转IoC
测试驱动系统架构
由模块化的关注面领域组成
使用单一语言对象实现
不同领域之间不具侵害性
侵害性架构会湮灭领域逻辑,冲击敏捷能力<br>导致缺陷隐藏,生产力下降
迭进
尽可能减少类和方法的数量
应当避免教条式的去遵循规定,比它更重要的是测试、消除重复和表达力
并发编程
并发是一种解耦策略,将目的和时机分解开,能明显的改进应用程序的吞吐量和结构
对于并发的一些说法
并发会在性能和编写额外代码上增加一些开销
正确的并发是复杂的,即便对于简单的问题也是如此
并发缺陷并非总能重现,所以常被看做偶然事件而忽略,未被当作真的缺陷看待
并发常常需要对设计策略的根本性修改
并发防御原则
限制数据作用域
无法预期的行为采用synchronized保护使用共享对象的临界区
使用数据复本
从多个线程收集所有复本的结果,并在单个线程中合并这些结果
线程应尽可能独立
java.util.concurrent包
执行模型
基础定义
限定资源
并发环境中有着固定尺寸或数量的资源。<br>例如数据库连接和固定尺寸读写等
互斥
每一时刻仅有一个线程能访问共享数据或共享资源
线程饥饿
一个或一组线程在很长时间内或永久被禁止。<br>例如:总是让执行得快的线程先运行,假如执行得快的线程没完没了,则执行时间长的线程就会“饥饿”
死锁
两个或多个线程互相等待执行结束。每个线程都拥有<br>其他线程需要的资源,得不到其他线程拥有的资源,就无法终止
活锁
执行次序一直的线程,每个都想要起步,但发现其他线程已经在路上。<br>由于竞步的原因,线程会持续尝试起步,但在长时间内却无法如愿,甚至永远无法启动
生产者-消费者模型
一个或多个生产者线程创建某些工作,并置于缓存或队列中
一个或多个消费者线程从队列中获取并完成这些工作
生产者和消费者之间的队列是一种限定资源
读者-作者模型
一个共享资源,主要为读者线程提供信息源,偶尔被作者线程更新
宴席哲学家
应对并发
避免使用一个共享对象的多个方法,如果必须则
基于客户端锁定
客户端在调用第一个方法前锁定服务器
基于服务端锁定
服务端内创建锁定服务端的方法,并调用所有方法
保持同步区域微小
尽早考虑线程关闭问题
测试线程代码
测试并不能确保正确性,但是能尽量降低风险
将偶发事件看作可能的线程问题
确保非线程代码可正常工作
编写可插拔的线程代码
编写可调整的线程代码
运行多于处理器数量的线程
在不同平台上运行
装置试错代码
硬编码
增加wait、sleep、yield等方法调用,改变代码执行顺序
自动化
Aspect-Oriented Framework
CGLIB
ASM