1) 通用方法
一个方法处理多个业务,比如修改用户传入一个用户对象,方法根据邮箱,手机..是否为空来处理修改手机,邮箱等业务
处理方法:每个业务要分开,单一职责
2) 对象内的平行方法
A(a1,a2,a3),a1,a2,a3方法中有相似功能。
IA(a)ßA(a,abstract b)ßA1(b),A2(b),A3(b)
3) 业务链方法
一个业务的链式判断用方法调用来实现,比如用户登录,先判断是否是用户名-》别名-》密码。
方案二:用责任链或装饰器模式来处理。
两个没有特别明显的优略,但如果是一个业务的重要逻辑,方案二有明显优势。
4) 混乱代码
很多类,对像协调来做一件事,每个类只是一个框子,代码间调用复杂。
最差的一种代码,用面向对象的架子来装下面向过程的代码,过程分的还不清晰。
处理方案:两条线索,1从重复代码入手重构(示例迁徙程序)。2.从不合理调用链条重构(示例画图模型和前台UI耦合重构)。
更进一步再是类的单一职责。
5) 混乱对象
对象转化多次来做一件事。比如转成一个批量Bean的临时对象,再生成批量Bean,再生成一个批量Bean的集合。
处理方法:找出有效转化,去除无效转化。
6) 线程滥用
到处是多线程协作。
处理方法:找到系统瓶颈,多线程的使用原因,去除对系统无贡献的多线程。
7) 提前调一下
调用方法A之前必须调用B方法,如画图前,要调用设置屏幕信息以及画布大小相关的方法。
处理方法:把B做成接口让相关类依赖,调用A时传入相关B接口实现。
8) 双向依赖
解除双向依赖,A->B B-A
方法一:使用依赖倒置原则。(把A中被B依赖的进行抽象放入B中)
方法二:新建立C,把A中被B依赖的放入C。
例:画图程序前台依赖于画图模型,画图模型需要依赖前台像素大小。画图模型依赖于ScreenInfo接口,前台类构建ScreenInfo实现传入模型。
此例子中不适用方法二,因为只有画的时候才能得到屏幕信息。
9) 业务关注缓存
业务当中耦合缓存相关代码
处理方法:业务不应该关注数据的存储实际介质,下层提供透明的接口,实现Repository有些理想化。可以在缓存和数据库之上简历一个Façade来透明化接口。
10) 分层清晰,对象多
分层清晰,但业务松散,过程化对象多,但调用关系多过所做事情。
处理方法:提高业务对象的内聚性。
此处很有代表性,这类代码应该算是面向过程中比较好的代码了。很好的体现了领域驱动和过程化驱动的差异。对象更合理。
11) ThreadLocal大量使用
代码不好阅读,ThreadLocal能不用就不用。在一些地方能画龙点睛,比如数据库连接。但别代替方法传值。
12) 重构半天跑不起来了
程序混乱,并且无单元测试。重构要小步,先加新功能再删除原来的功能,并且要分成几步(足够小),每步让程序能跑起来可测试。比如用一个传值结构替换原来的传值结构,要先加新的变量,但不要删除原来的变量,然后用新变量一个属性在这个方法中的调用来替换原来的变量引用。 又如,画图程序中新的画图逻辑一个线一个点的替换原有逻辑。先注释原逻辑中的一点代码,让功能消失,用新逻辑实现,再测试。