设计异味
设计异味是计算机编程领域,设计所用结构违背了基本设计原则并对设计质量有负面影响。[1]这个术语源自马丁·福勒在《重构-改善既有代码的设计》一书中描述的代码异味。[2]
不同作者对“异味”(smell)有不同的定义:
- N. Moha等:“代码与设计异味是差的解决方案,导致了实现与设计问题”[3]
- R. C. Martin:“设计异味是腐败的软件的气味”[4]
- Fowler:“异味是代码中特定的结构导致了重构的可能”[2]
设计异味指示了积累的设计负债(技术负债的主要维度)。Bug与未实现功能不算是设计异味。设计异味产生于很差的设计决策,使得设计脆弱、难于维护。在一个软件系统中辨别设计异味,应用适当的重构去除异味,避免积累技术负债,是好的实践。
在确定特定结构或决策是否算作设计异味时,上下文环境(如问题清单、设计生态圈、平台等)扮演了重要角色。很多时候,由于上下文环境所限,只好容忍设计异味。
常见设计异味
- 缺乏抽象(Missing abstraction)[1],如果使用数据泥团而不是创建抽象。也称作基本类型迷恋 [2]、数据泥团(data clumps)。[2]。
- 多方面的抽象(Multifaceted abstraction)[1],如果一个抽象有多重责任。也称作概念化的滥用[5]
- 重复的抽象(Duplicate abstraction)[1],如果两个或多个抽象有相同的名字或实现。也称作不同接口的可选类[2]、重复的设计品。[6]
- 缺乏封装(Deficient encapsulation)[1],如果一个抽象的一个或多个成员的被声明的可访问性超出了实际需要。
- 未利用的封装(Unexploited encapsulation)[1],如果客户代码使用显式类型检查(使用链式if-else或switch语句检查对象的类型)而不是雷雨封装在架构中的类型的变化。
- 破损的模块化(Broken modularization)[1],如果数据与/或方法本应在一个抽象中,却被分开放到了不同的抽象中。
- 不充分的模块化(Insufficient modularization)[1],如果一个抽象实际上还没有被彻底分解,如果进一步分解会减小其尺寸或实现复杂度。
- 循环依赖的模块化(Cyclically-dependent modularization)[1],如果两个或多个抽象直接或间接互相依赖(抽象之间紧耦合)。也称作循环依赖。[7]
- 未分解的架构(Unfactored hierarchy)[1],如果架构内部存在不必要的重复的类型
- 破损的架构(Broken hierarchy)[1],如果一个父类型与一个子类型概念上并不构成“IS-A”关系,这导致了替代性的破缺。也称作“继承的不当使用”[8]、无用“IS-A”[9]。
- 循环的架构(Cyclic hierarchy)[1],如果父类型依赖于它的某个子类型。也称作继承/引用循环[10]。
- 僵化(Rigidity):系统难以修改,因为每个改变迫使系统其他部分也要做出修改。
- 脆弱(Fragility):一个修改可能引发没有概念关系的其他地方的崩溃。
- 顽固(Immobility):很难把系统分离为可被其他系统重用的模块
- 粘滞(Viscosity):做正确的事比做错事更难。
- 不必要的复杂(Needless Complexity):设计包含了没有直接好处的基础设施。
- 不必要的重复(Needless Complexity):设计包含了本可以用一个抽象统一起来的重复的结构。
- 晦涩(Opacity):难以阅读与理解。不能很好的表达其意图。
面向对象设计的有助于消除异味的原则
面向对象设计的SOLID五大原则: 单一功能原则:一个类只应有一个“改变的原因”(即功能); 开闭原则:软件实体(类、模块、函数等)应当对扩展是开放的,对修改是关闭的; 里氏替换原则:子类型能替换基类型; 依赖反转原则:高层模块不应依赖于低层模块,二者应当依赖于抽象。抽象不应依赖与细节。细节应当依赖于抽象。 接口隔离原则:类应当有胖(fat)接口,可被分为方法的分组。每个分组服务于不同的客户集。客户不应当知道这些分组是在同一个类中。
参见
参考文献
- ^ 1.00 1.01 1.02 1.03 1.04 1.05 1.06 1.07 1.08 1.09 1.10 1.11 Girish Suryanarayana, Ganesh SG, Tushar Sharma (2014). "Refactoring for software design smells: Managing technical debt". Morgan Kaufmann. ISBN 978-0128013977
- ^ 2.0 2.1 2.2 2.3 2.4 Fowler, Martin (1999). Refactoring. Improving the Design of Existing Code. Addison-Wesley. ISBN 0-201-48567-2.
- ^ N. Moha, Y. Gueheneuc, L. Duchien, and A. Le Meur. "Decor: A method for the specification and detection of code and design smells". IEEE Trans. Softw. Eng., 36(1):20–36, January 2010. "Code and design smells are poor solutions to recurring implementation and design problems."
- ^ R. C. Martin. Agile Software Development, Principles, Patterns, and Practices. Addison-Wesley, 2003."Design smells are the odors of rotting software."
- ^ Trifu A. "Automated strategy based restructuring of object oriented code". In Proceedings of the 7th German workshop on software-reengineering (WSR); 2005.
- ^ Stal M. "Software architecture refactoring". Tutorial in The international conference on object oriented programming, systems, languages and applications (OOPSLA); 2007.
- ^ Page-Jones M. "The practical guide to structured systems design". 2nd ed. Prentice Hall; 1988.
- ^ Budd T. "An introduction to object-oriented programming". 3rd ed. Addison Wesley; 2001.
- ^ Page-Jones M. "Fundamentals of object-oriented design in UML". Addison-Wesley Professional; 1999.
- ^ Sefika M, Sane A, Campbell RH. "Monitoring compliance of a software system with its high-level design models". In Proceedings of the 18th international conference on software engineering, ICSE ‘96, Washington, DC; 1996. p. 387–96.