第七章
什么是敏捷设计
干净,简单,灵活,独立,易于理解,结构清晰,可读性强
腐化软件的气味
- “牵一发而动全身”,很难对系统进行改动,对一个地方的改动会引起系统其他地方的改动
- 对系统的改动会导致和改动概念无关的地方出现问题
- 不能抽离出可重用的部分
- 做正确的事情比错误的事情要困难
- 不必要的复杂性:设计中不包含具有任何直接好处的基础结构
- 不必要的重复
- 很难阅读,理解,不能清晰地表现意图
设计原则
单一职责原则(SRP)
只做一件事,完成一个功能,只有一个变化的方向维度
一个类,一个模块,一个函数,一个组件
开放-封闭原则(OCP)
软件实体:可以扩展模块的功能,不必修改模块的代码(对扩展开放,对修改封闭)
// 抽出变化方向一样的作为interface约束规则
interface Shape {
draw(): void;
}
interface ShapeComparator {
(s1: Shape, s2: Shape): number;
}
function drawAllShapes(
shapes: Shape[],
comparator: ShapeComparator): void { const shapesCopy = Array.from(shapes)
.sort(comparator);
for (const shape of shapesCopy) {
shape.draw(); }
}
class Circle implements Shape {
draw(): void {
}
}
class Rectangle implements Shape {
draw(): void {
}
}
TypeScript的学习使用
使用TypeScript写一个轮询接口的类
interface ajaxConfig {
method: string;
url: string;
data?: string;
dataType: string
}
let xhr = new XMLHttpRequest();
function ajax(config: ajaxConfig){
xhr.open(config.method, config.url, true);
xhr.send(config.data);
}
class Polling {
url: string;
interval: number;
private time: number;
callback<T>(value: T):T {
return value
};
constructor(url: string,interval: number,callback?: any) {
this.url = url;
this.interval = interval;
this.startPolling(callback ? callback :this.callback);
}
startPolling = (callback: any): void => {
this.time = setInterval(()=>{
ajax({
url: this.url,
method: 'GET',
dataType: 'json'
});
callback(JSON.parse(xhr.response))
},this.interval);
};
stopPolling = (): void => {
clearInterval(this.time)
};
}
let testPolling: Polling = new Polling('http://api.dbpe-cps.com/mock/74/user',2000);
setTimeout(()=> {
testPolling.stopPolling();
},8000);
为以下对象撰写interface
const obj1 = {
a: 1,
b: true,
c: (a, b) => a + b,
d: [1, 2, 3]
};
interface obj1Props {
a: number,
b: boolean,
c: (a: number, b: number): number => {},
d: number[] (Array<number>)
}
const obj2 = a => a + 1;
(a: number): number => {}
(a: number)=>number
class Clz4 {
a = 1;
constructor(value) {
if (typeof value === "number") {
this.a = value;
}
}
getA() {
return this.a;
}
setA(value) {
this.a = value;
}
}
const obj4 = new Clz4(123);
interface obj4Props {
a: number,
getA: number,
setA: (number): void
}
void和undefined的区别:
ts对静态类型的判断是在编译时进行,不是运行时进行,void表示只能通过类的set方法进行赋值,避免直接赋值改变变量
耦合和内聚
不同变化方向要分离(解耦),相同变化方向要合并(内聚)
Liskov替换原则(LSP)
子类型必须能够替换掉他们的基类型
违反LSP规则会导致脆弱性
LSP规则可以提高代码的可维护性,可重用性,健壮性
enum ShapeType {
Circle,
Square,
}
class Point {
x: number,
y: number
}
class Shape {
type: ShapeType,
Shape(type: ShapeType):ShapeType {}
}
依赖倒置原则(DIP)
依赖于抽象,抽象与具体细节分离,高层策略与低层实现分离
下层细节修改导致修改上层-僵化性,牢固性
牢固性
- 按钮和灯的开关,抽象出一个SwitchableDevice,避免按钮无法重用
- React Router
<HashRouter />:不调用浏览器接口(BOM)
<MemoryRouter />:window.location.assign
<HistoryRouter />:window.history.push
Link组件-historyApi
- antd表单组件Input:onChange事件值为e.target.value
接口隔离原则(ISP)
不应该强制客户依赖于他们不用的方法
分离interface
小结
- 软件开发的评价标准:满足需求,高效率
- 迭代的良性和恶性循环
- 不良设计的七种特征:
- 僵化性
- 牢固性
- 脆弱性
- 不必要的复杂性
- 粘滞性
- 晦涩性
- 不必要的重复
- 变化的方向和解耦:
- 相同的变化方向合并(内聚)
- 不同的变化方向分离(解耦)
- SOLID原则:单一职责原则,封闭开放原则,里氏替换原则,依赖倒置原则,接口隔离原则
网友评论