1 简介
“Software entities (classes, modules, functions, etc.) should be open for extension, but closed for modification.”
**
- Class不可以被修改,但可以被继承,添加新的属性和方法来扩展功能_ ```typescript abstract class FileWriter { write(content: string): number; }
// buffered for a large-size file class BufferedFileWriter extends FileWriter { write(content: string): number; write(buff: ArrayBuffer, off: number, len: number): number; skip(num: number): number; }
// able to rollback class RollbackFileWriter extends FileWriter { write(content: string): number; rollback(): boolean; }
- Function接口不可以被修改,但可以添加扩展参数来扩展功能
```typescript
// a.ts
export interface Options {
op1: string;
op2: number;
}
export function format(num: number, options: Options): string {
// ...
}
// b.ts
import type { Options } from 'a.ts';
import { format } from 'b.ts';
export interface Options {
op3: boolean;
}
export function format(num: number, options: Options): string {
// ...
}
2 Example
// @yy/sl-tools
const format = (value: number, platformName: platformNameTypes): string | null => {
const supportPlatforms = ['STOREFRONT', 'ADMIN', 'DASH'];
const hitPlatform = supportPlatforms.indexOf(platformName) === -1;
let baseFormatOptions;
if (window === undefined) {
return null;
}
if (hitPlatform) {
console.error('请传入第二个参数platformName,目前仅支持STOREFRONT、ADMIN、DASH');
return null;
}
if (platformName === 'STOREFRONT') {
baseFormatOptions = {
code: Cookies.get('currency_code'),
lang: Cookies.get('lang'), // 目前商家前台还没有该字段.. todo...
};
} else if (platformName === 'ADMIN') {
baseFormatOptions = {
code: Cookies.get('a_currency_code'),
lang: Cookies.get('a_lang'),
};
} else if (platformName === 'DASH') {
baseFormatOptions = {
code: Cookies.get('d_currency_code'), // 目前dash还没有该字段(预留)
lang: Cookies.get('d_lang'), // 目前dash还没有该字段(预留
};
}
return baseFormat(value, baseFormatOptions);
};
- 改变接口,不兼容旧版本:破坏client调用代码
- 无法估计有多少Client
- 海量回归测试
- 耦合其他应用代码:貌离神合,仅仅是空间上的隔离
- 应用修改影响公共包
- 公共包修改影响应用
- 耦合其他职责(读取Cookies):违反SRP原则
- 分离配置读取代码
- 约定接口或协议,而不约定实现
3 改进
configManager.ts
```typescript export enum StorageType { Cookies = ‘cookies’, SessionStorage = ‘sessionStorage’, LocalStorage = ‘localStorage’, IndexedDB = ‘indexedDB’, }
interface BaseOptions { type: StorageType; }
export interface Config { lang: string; code: string; }
interface CookiesOptions extends BaseOptions {
key: Record
interface SessionStorageOptions extends BaseOptions { // … }
type LocalStorageOptions = interace SessionStorageOptions;
interface IndexedDBOptions extends BaseOptions { // … }
export type ConfigOptions = CookiesOptions | SessionStorageOptions | LocalStorageOptions | IndexedDBOptions;
export function getConfig(options: ConfigOptions): Config { // …. }
- `currency.ts`
```typescript
import _ from 'lodash';
import type { CookiesOptions } from './configManager';
import { StorageType, getConfig } from './configManager'
let DEFAULT_OPTIONS: ConfigOptions = {
type: StorageType.Cookies,
key: {
lang: 'lang',
code: 'currency_code',
},
};
let options: ConfigOptions = DEFAULT_OPTIONS;
export function setOptions(opts: ConfigOptions) {
// merge
options = _.merge({}, DEFAULT_OPTIONS, opts);
}
export function formatCurrency(number) {
// ...
const config = getConfig(options);
// ....
}
- 使用 ```typescript // 应用Admin初始化: app.ts
import { setOptions, StorageType } from ‘@yy/sl-tools’;
setOptions({ type: StorageType.Cookies, key: { lang: ‘a_lang’, code: ‘a_currency_code’ }, });
// 使用 import { formatCurrency } from ‘@yy/sl-tools’; formatCurrency(number); ```