這輪 Stripe VO 整體給我的感覺很明確:更偏真實業務建模,而不是演算法刷題。開場流程非常乾脆,簡單自我介紹後,兩位面試官直接進入 coding 環節,全程圍繞「交易系統中的費用計算」展開,一共兩道題,邏輯逐步遞進。我對接了 oavoservice 團隊協助完成這輪 technical interview,下面把題目與解題節奏完整還原出來。
一、整體節奏:先 clarify,再動手
Stripe Coding 的一個鮮明特點是:寫程式碼之前的澄清比程式碼本身更重要。兩道題都是先拋業務背景,讓你自己問清楚規則邊界,再開始實現。如果一上來就悶頭寫,很容易寫出「能跑但不像生產程式碼」的東西。
| 階段 | 重點 |
|---|---|
| Clarify | 不同交易類型 / 狀態是否計費?邊界規則是什麼? |
| 建模 | 解析、交易模型、費用計算、輸出結果四層解耦 |
| 實現 | 避免把業務邏輯寫死,方便擴展和測試 |
| Followup | 新增交易類型 / 費率調整時改動是否可控 |
二、Part 1:解析交易 CSV,計算每個用戶費用
第一題給一個交易記錄的 CSV 字串,要求解析後計算每筆交易中每個用戶需要支付的費用。題目表面像字串解析,但真正寫程式碼前,面試官先拋了幾個關鍵澄清問題:
- 不同交易類型(支付、退款)是否適用不同費用規則?
- 處於 pending 或退款中的交易是否需要計費?
- 金額單位、精度怎麼處理?
規則確認清楚後,這題的重點就很明確了:不在 CSV parsing 本身,而在你能否在不把業務邏輯寫死的前提下,把費用規則表達清楚。
我的做法是刻意避免把所有邏輯堆在一個函式裡,而是先把職責拆開:
from dataclasses import dataclass
from typing import List, Dict
@dataclass
class Transaction:
"""交易模型:只描述基礎資訊,不摻雜費用邏輯"""
user_id: str
amount: int # 以最小貨幣單位儲存,避免浮點誤差
status: str # completed / pending / refunded
method: str
country: str
def parse_transactions(csv_text: str) -> List[Transaction]:
"""解析層:只負責把原始字串轉成結構化物件"""
txns = []
for line in csv_text.strip().splitlines():
uid, amount, status, method, country = line.split(",")
txns.append(Transaction(uid, int(amount), status, method, country))
return txns
費用計算邏輯單獨封裝,根據交易類型和狀態應用對應規則:
def fee_for(txn: Transaction) -> int:
"""費用層:規則集中在這裡,解析邏輯不污染業務邏輯"""
if txn.status != "completed": # pending / refunded 不計費
return 0
if txn.method == "refund":
return 0
# 基礎規則:2.9% + 固定 30(最小貨幣單位)
return round(txn.amount * 0.029) + 30
def total_fee_per_user(csv_text: str) -> Dict[str, int]:
result: Dict[str, int] = {}
for txn in parse_transactions(csv_text):
result[txn.user_id] = result.get(txn.user_id, 0) + fee_for(txn)
return result
這樣拆分的好處很直接:解析邏輯和業務規則不會互相污染,未來新增交易類型或費用規則,只需改動對應模組,不會牽一髮而動全身。
面試官的 followup 幾乎都圍繞工程可維護性:
- 如果未來多了一種交易狀態怎麼辦?→ 答:狀態判斷集中在
fee_for,新增分支即可,解析層不動。 - 費用規則調整是否需要重構?→ 答:規則是資料 + 單一函式,調整成本低。
- 如何保證邏輯清晰、容易測試?→ 答:每層都是純函式,可單測。
這些問題本質上不是在考「能不能寫出來」,而是在看你是不是習慣用工程化方式思考。
三、Part 2:基於國家與支付方式的動態費率
第二題在第一題基礎上深化,只對 completed 的交易做進一步處理,並引入國家和支付提供商兩個新變數。不同國家、不同支付方式對應不同費率結構,要算出最終實際費用。
這裡我選擇用 查找表(Lookup Table) 處理費率,而不是堆一堆 if-else:
# (payment_provider, buyer_country) -> (variable_rate, fixed_fee)
RATE_TABLE = {
("visa", "US"): (0.029, 30),
("visa", "DE"): (0.014, 25),
("visa", "FR"): (0.014, 25),
("visa", "AT"): (0.014, 25), # 同費率國家也分別列出,保持實現簡單可讀
("paypal", "US"): (0.034, 49),
}
DEFAULT_RATE = (0.039, 30) # 兜底費率
def dynamic_fee(txn: Transaction) -> int:
if txn.status != "payment_completed":
return 0
rate, fixed = RATE_TABLE.get((txn.method, txn.country), DEFAULT_RATE)
return round(txn.amount * rate) + fixed
這個設計的優勢很明顯:
- 規則集中在一處,邏輯直觀;
- 新增國家或支付方式時,只更新查找表,不影響主流程;
- 避免多層條件判斷導致的可讀性和維護性問題。
對於德國、法國、奧地利這類費率相同的國家,我也選擇在查找表裡分別列出,而不是額外做國家分組抽象——保持實現簡單、可讀,這正是 Stripe 想看到的取捨。
四、面試整體評價
整體來看,這輪 Stripe VO 不難在演算法本身,而是考你是否具備把業務問題工程化的能力。面試官更關注:
- 對需求的理解是否到位(clarify 充分);
- 資料模型是否合理(分層解耦);
- 程式碼結構是不是符合真實生產環境的寫法;
- 設計時有沒有提前考慮擴展性和各種邊界情況。
如果平時更習慣用 LeetCode 模板思路解題,很容易在這種題裡顯得「能寫出來,但不太像實際工程程式碼」。
五、總結
Stripe Coding 的評分錨點是工程化實現品質:先 clarify 再動手、按職責分層、用資料(查找表)代替硬編碼分支、隨時回應擴展性 followup。把這套思維練成肌肉記憶,比多刷幾十道 hard 更管用。
FAQ
Q1:Stripe VO 的 Coding 到底考什麼?
考真實業務建模而非演算法技巧。本輪兩題都圍繞「交易費用計算」遞進:Part 1 解析 CSV 算每個用戶費用,Part 2 引入國家 / 支付方式做動態費率。重點是分層解耦與擴展性。
Q2:為什麼用 Lookup Table 而不是 if-else?
費率規則隨國家 × 支付方式組合膨脹,if-else 會越堆越亂。查找表把規則集中成資料,新增組合只改一行表,主流程不動,可讀性和可測試性都更好。
Q3:面試官的 followup 一般問什麼?
幾乎都圍繞工程可維護性:新增交易狀態怎麼辦、費率調整要不要重構、如何保證可測試。答題時強調「分層 + 純函式 + 規則即資料」即可對上他們的評分點。
Q4:怎麼準備 Stripe Coding?
把「先 clarify 再動手」練成習慣,刻意訓練分層(解析 / 模型 / 規則 / 輸出)寫法,並對每個設計點準備好擴展性回答。如果想要這兩道真題的限時陪練,或需要 VO代面 / VO輔助 的即時對接,可以發崗位 JD 先做題型預測再排練習計劃。
正在準備 Stripe 面試?
Stripe VO Coding 考的是工程建模 + 分層解耦 + 擴展性思維,不是刷題量。oavoservice 提供 Stripe 全流程陪練:交易費用建模、Lookup Table 取代 if-else 的取捨演練、followup 應答訓練,也支持 VO代面 / VO輔助 的即時對接。教練含前大廠資深工程師,熟悉 Stripe「願意 merge 的程式碼品質」評分風格。
立即添加微信 Coding0201,獲取 Stripe 真題與陪練。
聯絡方式
- 微信:Coding0201
- Email:[email protected]
- Telegram:@OAVOProxy