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.tsexport interface Options {op1: string;op2: number;}export function format(num: number, options: Options): string {// ...}// b.tsimport 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-toolsconst 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````typescriptimport _ 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) {// mergeoptions = _.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); ```
