Upgrade to Pro
— share decks privately, control downloads, hide ads and more …
Speaker Deck
Features
Speaker Deck
PRO
Sign in
Sign up for free
Search
Search
Refactoring lesson : from GPA 1.4 to GPA 3.0
Search
Yi-Ting Cheng
September 24, 2016
Technology
8
1.6k
Refactoring lesson : from GPA 1.4 to GPA 3.0
RubyConf China 2016 - Xdite
Yi-Ting Cheng
September 24, 2016
Tweet
Share
More Decks by Yi-Ting Cheng
See All by Yi-Ting Cheng
Blitzbuilding Product with Rails
xdite
2
1.6k
第六屆做自己論壇 - Xdite 鄭伊廷
xdite
4
5.7k
全棧班畢業贈語
xdite
1
40k
Intro to RedPotion
xdite
0
250
莫拉克颱風災情支援網
xdite
1
360
Intro to self Growth Hack
xdite
61
20k
Building a workshop / community
xdite
6
1.2k
Building SaaS using Rails
xdite
15
2.1k
Maintainable_Rails_View.pdf
xdite
29
2.3k
Other Decks in Technology
See All in Technology
Reactフレームワークプロダクトを モバイルアプリにして、もっと便利に。 ユーザに価値を届けよう。/React Framework with Capacitor
rdlabo
0
130
PaaSの歴史と、 アプリケーションプラットフォームのこれから
jacopen
7
1.5k
Formal Development of Operating Systems in Rust
riru
1
420
Docker Desktop で Docker を始めよう
zembutsu
PRO
0
180
メールヘッダーを見てみよう
hinono
0
110
AWSの生成AIサービス Amazon Bedrock入門!(2025年1月版)
minorun365
PRO
7
470
【JAWS-UG大阪 reInvent reCap LT大会 サンバが始まったら強制終了】“1分”で初めてのソロ参戦reInventを数字で振り返りながら反省する
ttelltte
0
140
Accessibility Inspectorを活用した アプリのアクセシビリティ向上方法
hinakko
0
180
Git scrapingで始める継続的なデータ追跡 / Git Scraping
ohbarye
5
500
シフトライトなテスト活動を適切に行うことで、無理な開発をせず、過剰にテストせず、顧客をビックリさせないプロダクトを作り上げているお話 #RSGT2025 / Shift Right
nihonbuson
3
2.2k
機械学習を「社会実装」するということ 2025年版 / Social Implementation of Machine Learning 2025 Version
moepy_stats
5
1.3k
新卒1年目、はじめてのアプリケーションサーバー【IBM WebSphere Liberty】
ktgrryt
0
130
Featured
See All Featured
Into the Great Unknown - MozCon
thekraken
34
1.6k
How to train your dragon (web standard)
notwaldorf
89
5.8k
Raft: Consensus for Rubyists
vanstee
137
6.7k
ピンチをチャンスに:未来をつくるプロダクトロードマップ #pmconf2020
aki_iinuma
113
50k
GitHub's CSS Performance
jonrohan
1030
460k
The Cult of Friendly URLs
andyhume
78
6.1k
Producing Creativity
orderedlist
PRO
343
39k
Statistics for Hackers
jakevdp
797
220k
How to Create Impact in a Changing Tech Landscape [PerfNow 2023]
tammyeverts
49
2.2k
XXLCSS - How to scale CSS and keep your sanity
sugarenia
248
1.3M
For a Future-Friendly Web
brad_frost
176
9.5k
Sharpening the Axe: The Primacy of Toolmaking
bcantrill
38
1.9k
Transcript
Refactoring lesson : from GPA 1.4 to GPA 3.0
About me • xdite • 微信号 xxddite • 公眾号 Xdite
全栈营教头 • Ruby on Rails • Agile • Growth Hack
• 认知⼼心理学 + 技术教学 https://ruby-china.org/topics/31080 無編程經驗的新⼿手,如何在四周開發實戰等級產品
为什么会来这次⼤大会 • 刚好我在北京 • 筹备组就问我要不要来 • 顺便投⼀一个题⺫⽬目 • 去年我都没有在燃烧我的激情 (
a.k.a 写 code ) • 想了⼀一下还是投了⼀一个题⺫⽬目
Refactoring lesson : from GPA 1.4 to GPA 3.0 酷,程序员听到「翻修」就充满激情
1.4 -> 3.0 codeclimate.com
3.0
1.4
背景故事
2014 年 7 ⽉月 • 矽⾕谷 O2O 送餐公司 • 种⼦子轮
拿了 250 万美⾦金 • A 轮拿了 1100 万美⾦金 • 来台湾征才 • 8 ⼈人公司加⼊入了 SpoonRocket • 公司⼤大举招⼈人
• Angular - 客⼾戶 Web 端 • Android • iOS
• Rails - Admin • jQuery - Dispathcher (⼈人⼯工配餐台)
• 2 ⼈人技术团队,⼀一个⽉月之内扩编到 20 ⼈人 • ⼤大家就⼀一直踩到隔壁的脚
• 虽然技术团队 20 ⼈人 • 每天可以拉上超过 20 ⽀支 pull-request •
但是每天只能 deploy 2 ⽀支 pull-request • 凌晨 3:00 (台湾时间)开店,SA 只能睡公司....
• 经常性 Rollback • 20 ⼈人还是只有 2 ⼈人战⼒力 • 每天开店⽼老是炸
• ⽆无法做促销,呼叫⼀一只菜单 API ~= 700ms • 开启 Admin Controller 超过 60 秒
• 刚加⼊入没多久就后悔 • Grape API • 每⼀一只 Grape API 约
1000-2000 ⾏行 • 毫⽆无逻辑的 EndPoint • 重复逻辑到处复制贴上 • Admin 后台的单⼀一 index action 也⾼高达数千⾏行
• CTO 与第⼀一个 RD。凭借蛮⼒力硬是上线 • 永远保持能卖东⻄西就好 • 我⻅见识到的是 GPA 1.0
的代码也能募到这么多钱.... • 所以代码是否干净与能不能赚钱没有关系
⼈人⼈人都想 Refactor
但⼈人⼈人都不想 Refactor
• ⾝身为 RD Lead • ⼤大便只能由我先吃 • 毕竟这是我的⼯工作..
結果 • API 代码 95 % 以上覆盖 • 上了 CI
• 全代码覆盖率 60% • GPA 3.0
挑战 1 :从哪⾥里开始?
• 快 100 只 API • 50 只以上 Controller •
快 70 个 model • 10000 多⾏行代码
答案:先补⽂文档
WIKI 上必须要有主要 API 的⽂文档 • GET / POST • 输⼊入参数
/ 输出结果 • 回传值 • (真实资料)
• 取得全局感 • ⼤大致上有多少 API 我们得⾯面对 • 估计⼯工作量 • 估计「重构」所损失的战⽃斗⼒力
( 必须公司可承受)
⽼老板说他只能承受 2 周没有⽣生产⼒力...
⽼老板说他只能承受 2 周没有⽣生产⼒力... 当然事实上是 1 天 都不能没有
挑战 2 :先写哪边的 Test ?
答案:先写 API Test
• 把每⼀一⽀支 APP 都开⼀一⽀支 Redmine Ticket
实作步骤 • 半强迫每个 RD,⼀一个礼拜必须写 10 ⽀支测试 • 没时间也⾄至少做到 • API
200 • 验证格式正确 • ⼿手头掰不出测试资料就使⽤用「真实资料」
• 牵涉到 3rd Party 的 API 不写 Test • 呼叫演算法的
API 不写 Test • 因为代码太渣了,⽆无法强⾏行 mock…
• ⼀一个礼拜补完所有 API Test …(⾄至少有 200 与格式) • ⾄至少 RD
要是拉 pull request,没有绿灯就可以叫他滚 回去了 • 快速滤掉第⼀一层低级错误 • rollback 率⼤大幅下降
挑战 3 :先重构哪部分的代码 ?
从 API 分离下⼿手 • Before : ⼀一⽀支 API 档案 >
1000 ⾏行代码 • After :⼀一⽀支 APP 的「档案」必须⼩小于 160 ⾏行
从 API 分离下⼿手 • 原先 API ⼤大约有 10 个 Endpoint
• 降到 3 个 End Point
开始有办法清楚的看懂代码
闪坑 • 不会再被 if / else 坑到 • 不会再也不知道⾃自⼰己再改那个 end
point 的代码 • 有机会把「相近」的 Resource 放在同⼀一个档案 • 因为有 200 Test 可以放⼼心的搬家
抽出业务逻辑 • 把业务逻辑搬到 ServiceObject • API 只负责呼叫 Service Object •
API 的 Test 只负责验证 200
None
None
• 添加 error! • 将业务逻辑细细拆分 • 终于可以仔细拆分不同 状况,不需到处 mock •
甚⾄至可以开始 stub ServiceObject
开始处理⽆无法 Mock 的 API • 要求「演算法」也抽出成 ServiceObject • 不测试演算法 •
但 API 必须补「格式」Test
⼩小结
• Step 1: 先估计「⼯工作量」 • Step 2: 装上红绿灯,⾄至少保证永远有基础绿灯。 • Step
3: 切细变成可以「重构」的区块 • Step 4: 盒⼦子打包法,补⿊黑盒⼦子测试
挑战 4 :补「重构」哪部分的代码 ?
CodeClimate Refactor 法 • 找出 F 等级代码。 • 专攻重复区域,打包成 method,补
unit test。 • ⼜又补了⾄至少 > 50 个 Test • 重复的代码 = 重要的业务逻辑(到处都⽤用到)
• ServiceObject (商业流程) • Calculator ( 计费可以随时抽换不同公式 ) • Validator
( ⼀一个 Order ⾄至少要经过 10 道验证,把验证做到可叠 加 ) • Serializer ( 原先是 Hash,改⽤用 Serializer 好管理 ) • Cells ( 让 View 可重复使⽤用 ) • StrategyClass ( 可策略抽换应付「营销活动」与「价格模型」 ) • Worker ( 把效能瓶颈移到背景去执⾏行 ) • Concern ( 复合使⽤用把常⻅见⼯工具类 method )
ServiceObject • 查价 / 库存 • 下单 • 退单 •
跟踪订单 • 计算运送所需时间 • 不同版本 API,使⽤用不同 ServiceObject
None
Calculator • 不同地区不同税率 • 冷的不收税、热的收税 • 司机⼩小费 • 礼物卡的税务逻辑
Strategy • 地区营销活动 • API 上可插拔 • 活动结束直接关掉 Strategy
Worker • 付款呼叫 Stripe • 伪卡 • 霸⺩王餐⾏行为
SOA • 演算法 • Dispatcher (⾼高 JavaScript 耦合)
⼩小结
• 每个业务逻辑的接⼝口必须干净,容易插拔 • 每整理⼀一个业务模块,就补 Test • 修改 / 新增功能,必须补 Test
花了 1 个⽉月
• 2 pull request => 5 => 10 • 终于可以上
CI server • 不是绿灯,pull request 不会有⼈人理
讲完 API ,来讲 Controller
• ⼀一个 Controller ⼏几千⾏行代码 • ⽼老板把逻辑都写在 JavaScript ⾥里⾯面
• 因为 Dispatcher 台是 JavaScript 写的 • 只好其他业务逻辑也⽤用同样的⽅方式
第⼀一步 • 把 Dispatcher 「以外」的部分搬去 Rails CRUD • 不太需要写 Test
• 烂了请美国同事 hotfix,也不影响消费者下单 • 拆了 ~15 ⽀支 Controller
第⼆二步 • 把 Dispatcher 当作是 Client • 不再是 Rails 与
JavaScript 混合产⽣生 View • 显⽰示逻辑都使⽤用 JavaScript • Rails 作为 API 提供资料 • 补 API Test
• Frontend 组搞了很久 • 巨坑.... • 那时候剛有 React, … •
学到以后复杂逻辑绝对別⽤用 jQuery 先搞。
经过这⼀一轮 • 1 个⽉月就从 1.4 => 2.95 • 代码覆盖率到 40%
+ • 花了另外的 5 个⽉月 2.95 => 3.06 • 花了另外的 5 个⽉月代码覆盖率到 60% • ⾜足够好
挑战 5 :Release 太快带来的问题
• 每天 Release 15 ⽀支 pull request • db migration
或是改资料,还是个坑,需要⼈人为介⼊入 • 运营团队抱怨虽然没有 500,但是业务逻辑⼀一直在变 • 应该要出 Release ⽇日报
zendesk/samson
⼀一键 deploy
None
Deploy 架构 • samson 修改版 for heroku deployment • heroku
pipeline
• ⾃自动汇集 pull request 成 deploy ⽇日报 • 必须叙述作⽤用 •
若有 migration 必须在 #Risk 环节注记 • Deploy ⾃自动执⾏行
成果 • GPA 3.06 • 60 % test coverage •
15 pull request/day • API has ~95% test coverage. • major API response time < 80 ms • We shipped 6-8 major features every week.
Take away • 先搞清楚有多少测试要写。 (否则会遭到公司否决) • 先写 Integration Test •
Integration test -> Service Object test -> Unit test • 尽量提供 developer 「动机」去写 • 测试资料 • 可复制的测试代码
Take away • 做 Refactor 前⼀一定要先上 Test • 前期⺫⽬目标是「有动机去做」 •
中期⺫⽬目标是「接⼝口干净」 • 远期⺫⽬目标是「⾃自动部署」
不过
• 虽然「补测试」这么不爽 • 之后创业我还是不会先写测试 • 因为我理解了 GPA 1.0 还是可以拿到 1100
万美⾦金 • 商业的重点是「测试」你的 「idea」,⽽而不是「代码」 • 赚了钱你要雇⼏几个⼤大⽜牛来帮你重构都⾏行
Q & A