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
350
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
DynamoDB でスロットリングが発生したとき/when_throttling_occurs_in_dynamodb_short
emiki
0
260
テストコード品質を高めるためにMutation Testingライブラリ・Strykerを実戦導入してみた話
ysknsid25
7
2.7k
Shopifyアプリ開発における Shopifyの機能活用
sonatard
4
260
20241120_JAWS_東京_ランチタイムLT#17_AWS認定全冠の先へ
tsumita
2
300
強いチームと開発生産性
onk
PRO
35
11k
SSMRunbook作成の勘所_20241120
koichiotomo
3
160
FlutterアプリにおけるSLI/SLOを用いたユーザー体験の可視化と計測基盤構築
ostk0069
0
110
インフラとバックエンドとフロントエンドをくまなく調べて遅いアプリを早くした件
tubone24
1
430
TanStack Routerに移行するのかい しないのかい、どっちなんだい! / Are you going to migrate to TanStack Router or not? Which one is it?
kaminashi
0
600
BLADE: An Attempt to Automate Penetration Testing Using Autonomous AI Agents
bbrbbq
0
320
ノーコードデータ分析ツールで体験する時系列データ分析超入門
negi111111
0
420
CDCL による厳密解法を採用した MILP ソルバー
imai448
3
170
Featured
See All Featured
個人開発の失敗を避けるイケてる考え方 / tips for indie hackers
panda_program
93
16k
Building Flexible Design Systems
yeseniaperezcruz
327
38k
What’s in a name? Adding method to the madness
productmarketing
PRO
22
3.1k
GitHub's CSS Performance
jonrohan
1030
460k
ピンチをチャンスに:未来をつくるプロダクトロードマップ #pmconf2020
aki_iinuma
109
49k
Build The Right Thing And Hit Your Dates
maggiecrowley
33
2.4k
Designing the Hi-DPI Web
ddemaree
280
34k
[RailsConf 2023 Opening Keynote] The Magic of Rails
eileencodes
28
9.1k
Art, The Web, and Tiny UX
lynnandtonic
297
20k
BBQ
matthewcrist
85
9.3k
[RailsConf 2023] Rails as a piece of cake
palkan
52
4.9k
Creating an realtime collaboration tool: Agile Flush - .NET Oxford
marcduiker
25
1.8k
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