重构!重构!重构!

站在用户的角度而不是程序员的角度来思考问题,才能设计出好的软件!

从要实现的所有系统功能清单(用例)中选取最重要的,优先编程实现。

根据能投入开发的人力和物力资源设计切实可行的开发计划。

当你发现在程序中有多个地方都需要实现同一功能时,请将此功能代码抽取为独立的可重用的组件,不要到处Copy & Paste。You Ain’t Gonna Need It(绝不“画蛇添足”YAGNI原则)

用最简单的方法,仅仅只实现你所需要的功能。
在确实需要时,才进行抽象和封装
不要“想象”用户会需要什么,自作主张地在系统中添加新功能。

不要过度设计,在满足需求的前提下,采用的软件设计方案越简单越好。
KISS原则的另两种表达:Keep It Short & Simple(追求短小精悍);Keep It Simple & Straightforward(追求简洁明了)

Don’t Do It Yourself(不要一切自己动手)不走极端,要走“中庸”之道

针对一些简单的问题,使用各种“框架”,确实显得“用牛刀杀鸡”,并非最佳方案。
全部自己动手,则开发效率较低,隐藏BUG较多,系统不易稳定,亦非最佳选择
多数场景下,尽可能地复用,但不排除在特定场景下“自己动手”,“重新发明轮子”或“造新轮子”。

文档和UML图本身不是设计,最后产生的程序和代码才是设计

僵化的设计:设计无法响应需求和外部环境的变化,一有改变,必须推翻重来。 

在代码中“写死”要读取的文件路径
UI控件直接设定底层数据源的字段名
数据库表要加一个新的字段,结果导致N处地方需要更改

脆弱的设计

“不敢”对软件进行改动,进行一个小的改动,其他地方就出错,甚至整个系统崩溃……

无法重用的设计

系统中包容了对其他系统有用的部分,但是要把这些部分从系统中分离出来,却非常困难:

过于复杂的设计

完成一件事情有N种方式,选择复杂的那种。

明明可以用Python写个小程序就能解决的问题,用C++来写……
我需要保存一些数据到数据库的一个表中,使用Entity Framework这种重量级的框架……

想得过多,过度设计。

为了未来“可能发生”的变化,我先写一些可以应付这些变化的代码……
唔,我要实现这个功能,有一个“XXX模式”正好用上,就用它吧……

区分命令与查询

对象的状态

在某个一时刻,对象所有字段/属性值的集合构成对象的“状态”。
Tell, Don’t Ask(告诉,而不询问):你应该告诉对象你需要他们干哪些事,而不要去查询他们的状态,再依据这些状态来决定你该采取什么行动。这些工作,应该封装到类的内部,由类自己完成。
应用这条原则有助于避免类之间的紧耦合。

命令 vs 查询

类所定义的所有方法,可以分为两类:
直接修改对象的字段值,导致其状态改变(或者对外部环境有直接影响)的,称为“命令(Command)”
仅提取信息,并不改变对象自身及外部环境状态的,称为“查询(Command)”

命令方法的执行会改变对象的状态,因此它是有“副作用( side effects )”的,而查询方法则不会。
命令方法内部可以调用查询方法,但查询方法一定不能调用命令方法。
命令方法通常没有返回值,而查询方法肯定有返回值。
查询能够被安全地调用多次。

类方法设计的准则

你向对象发出的要不是Command,要不是Query,而不能同时是Command和Query。
如果一个方法既是命令又是查询,那么不看代码,你是不知道它能做什么事的。

区分命令和查询,有助于提升代码的可读性。

 

 

 

 

不要生搬硬套,应该在理解的基础上活用这些知识。
• 在实际开发中,不要强求一开始就能把类设计得很好,而应该用好“重构”这一利器:先把东西做出来,然后再不断地重构……

什么是类的职责?

类的“职责(Responsibility)”,指的是类实现的功能和承担的数据处理任务。
+ OOD设计原则:
• 每个类的职责必须明确;
• 每个类只承担一项职责。

避免过大的类

God object:指的是能“干一切事”的类,它就象上帝一样,负责”创造一切“,有它,其它的类都要靠边站。
C#中的Socket类,定义有27个属性,近100个方法
类承担的职责越多,它就越容易受到外界的影响,因为各种原因必须修改它的可能性就越大。

General Responsibility Assignment Software Pattern(通用职责分派软件模式GRASP原则)

•Creater
•Controller
•Pure Fabrication
•Information Expert
•High Cohesion
•Indirection
•Low Copupling
•Polymorphism
•Protected Variations
应用这些原则有助于在设计确定一个类的职责。

Expert/Information Expert原则

Assign the responsibility to the class that has the information needed to fulfill it.某项功能需要某些必要的信息,这些信息在哪个类中,就让这个类承担这项职责。

比如,“消费者(Customer)”想知道他己经订购了哪些“商品(Item)”,这个功能可以由“购物车(ShoppingCart)”所实现:

 Creator原则

这一原则要求设计者想清楚一件事:谁负责创建对象?

+比如,请看以下类:

 这两个类有着密切的关联,现在的问题时,创建Page对象的功能到底由谁负责?是外部代码还是归属于Document?

在《设计模式》一书中,列举了多种与对象创建相关的设计模式:Factory Method、Builder、Prototype、Singleton……
Controller原则
+考虑:谁负责显示数据?谁负责响应事件?谁负责处理数据?……

经典设计模式:MVC
在MVC设计模式中,由Controller(控制者)负责协调一切。

不要在实现业务逻辑的代码中访问UI控件
不要在UI代码中直接嵌入实现业务逻辑的代码。

 High Cohesion / Low Coupling

Coupling(耦合性): 用于衡量对象之间依赖性的强弱
+ Cohesion(内聚性): 用于衡量某个类所提供的外部功能及内部代码之间关联的紧密程度
在设计类时,追求“低耦合,高内聚”

实现 “低耦合,高内聚”的有效方法:组合优先于继承

 这么做的理由:继承在父类与子类之间建立了很强的耦合性,对父类成员的修改,有可能会影响到它所有的子类。

Indirection(间接性)原则

对象之间相互关联,形成了复杂的交互网络

为减少耦合,创建一个中间对象,将多对多关联拆散为一对多关联

 Pure Fabrization原则

当某些功能不适合于归属到特定的业务逻辑相关
的类时,创建一个新的类,这种类被称为“Pure Fabrication”,就是“生造出来的类”。

 这种类往往起“XXXService”这样的名字:
public class SystemService{
  public void SaveSystemArgument(){}
  public vlid Exit();
  public void BackupSystem();
}
使用这一思路,有助于实现“低耦合,高内聚”

Protected Variations 原则

这一原则可译为“隔离变化”原则,
+ 简单地说:在设计类时,应该尽量让其少受外界的影响。
“隔离变化”,是OOD的最终目的之一,有许多手段可以采用。
Polymorphism(多态性)原则

利用多态特性,把变化封装到子类中

from 面向对象软件开发实践之基本技能训练第5单元_第五单元:山重水复疑无路,柳暗花明又一村第2章_5.2 万丈高台,起于垒土——类设计指南

原文地址:https://www.cnblogs.com/Chary/p/14120811.html