如何做重构或者优化方案

明确目标

明确要解决的业务或者技术问题
  • 设立标准:怎么样算解决?当前的状况是什么样?理想的状况是什么样?
  • 明确问题:当前有什么问题,带来了什么问题
粗估成本收益
  • 投入的成本:包括设计,实现,验证,切换
  • 获得的收益:显性的,包括功能,效率,故障率,等等;隐形的,包括结构,使用,扩展,等等
对业务和系统有深刻的认知
  • 千万注意:什么样是一整套方案,什么样是打补丁方案。前者从根本上解决问题,后者解决表面问题
  • 在整体的基础上,确定影响范围
敢想:做正确的事
  • 清楚认知当前的本质问题,然后做正确的解决方案
  • 针对本质的问题和解决方案,不妥协。考虑拆分项目,分批次实现等方案,来降低复杂度
  • 针对细节的问题和解决方案,可以适当妥协。但不能危害整体的目标

确定整体范围

评估影响范围:外部
  • 影响哪些对外接口
  • 影响哪些外部业务和系统
  • 影响哪些外部使用方
评估影响范围:内部
  • 影响哪些内部核心数据结构
  • 影响哪些内部底层模型
  • 影响哪些内部业务和系统
  • 影响哪些内部使用方

制定整体计划

整体要有期望
  • 有deadline要求:根据deadline倒推计划
  • 无deadline要求:推算一个相关靠谱紧凑的计划
成功标准明确
  • 明确定义成功和失败标准,能清楚的衡量这些标准,能简单的获得基准数据
广度优先 vs. 深度优先
  • 广度代表了对整体的把握,广度意味着优先全面思考问题,不遗漏主要的影响范围
  • 深度代表了对细节的把握,深度意味着在某个相对独立的领域的认真细致的梳理,不遗漏任何细节
  • 先广度 -> 后深度
  • 广度往往不能并行,深度往往可以并行
穷尽多种方案
  • 方案往往不止一种,把不同思路的可对比的方案罗列出来,进行比较
  • 比较的点要能逻辑说明好坏,或者数字比较优劣
  • 讨论并选择最合适的方案,然后执行

制定执行计划

能并行执行
  • 合理拆分,接口清晰,标准明确
  • 此时再细致考虑资源问题,根据并行度投入资源
设计切换和回滚方案
实现排查问题的机制和工具
设立测试基准和新老逻辑/数字比对基准
  • 测试是标准化的,测试组件/case也是标准化的

常见策略

拆分
  • 多条业务线,一条一条拆分进行
  • 几个步骤,拆分进行;未进行的步骤使用原有方案或者毛招方案
比对
  • 同时运行新老两个流程,比对结果是否正确
  • 当结果完全一致或者正确率达到一个阈值时,进行切换
适配
  • 对使用方来说,接口保持不变,因此没有任何变化
  • 把新实现的逻辑适配到老的接口上

如何出数(报表)思路

弄清报表意义

解决什么问题
  • 为了解决某一个问题,我需要出一个报表
  • 不针对实际问题的出数都是耍流氓
展示什么现实
  • 事实不能被歪曲
  • 事实有很多,选取合适的事实,说明想说明的现实情况
谁需要看这个报表
  • 谁提出问题
  • 谁解决问题
  • 谁决策

设计报表内容

选取合适的周期
  • 小时报/日报/周报/月报/不定时
选取合适的粒度
  • 时间粒度:分钟/小时/天/周/月
  • 领域:SKU/门店/供应商/仓库
分层次的展示
  • 多粒度

分析事实数据

简单分析:汇总
  • 总计多少数据
  • 有多少case是delay的?
周期内分析:粒度
  • 有问题的SKU占比多少?
  • delay的case占比多少?
跨周期分析:比较
  • 有问题的SKU和上周比较的变化是多少?
  • delay的case比上周减少了多少?
整体分析:业务含义
  • 报表的数字,含义是什么?
  • delay的case比上周减少了10%,意味着什么?

学会写代码

关于代码

合理换行
合理空行
写注释和更新注释
最小变量作用域

关于方法

突出主流程
典型案例-badcase
void doSomething(...){if(? == null) {throw new Exception();} if(a == "") {a = "abc" + name;} List l = new List();for (i in array) {result = aService.aservice(i);if (result == 1) {l.add(result);}} bService.bservice(l); ......}

1. 主流程和分支流程冗杂
2. 方法篇幅巨大
3. 非常难以阅读


典型案例-改进
void doSomething(...){// 1. 校验参数verifyParameter(...);// 2. 调用a服务List l = handleA(...); // 3. 调用b服务handleB(l); // 4. 其他处理......} void verifyParameter(...) {......}void handleA(...) {......}void handleB(...) {......}

Icon

clean code里面建议
1. 一个类不要超过50行
2. 一个方法不要超过5行

OK,我承认这个有点激进,但是根据经验稍微放宽标准之后是都能做到的
1. 一个类不要超过200行
2. 一个方法不要超过20行

(针对绝大多数case,一定会出现反例,具体问题具体分析)

相信我,都能做到,只是需要一点耐心和脑筋

起个合适的名字

Icon

我们不要最牛的,不要最怪的

我们要的是最“合适”的

注意区分:trim,trimToNull,trimToEmpty

强烈推荐无副作用的方法

关于类

注意类和包的层次
从类开始一次只专注一件事
合理使用继承

方便阅读

Icon

写代码当然要能执行,但是写能执行的代码很容易,我们不纠结一次

我们强调的是写容易阅读的代码

1. 好的代码应该能“自解释”,这需要你有良好的结构/命名/符合通用的设计思路

2. 不好理解的部分才需要注释

3. 最可怕的是写了注释别人都理解不了

设计模式

推荐:静态构造
推荐:builder
推荐:策略