計與落地實踐)
先說結(jié)論open-code-review 是我自己維護的一個開源 Code Review 輔助工具核心作用是把代碼評審從“人肉找茬”變成“人機協(xié)作”。它不代替 Reviewer 做最終判斷而是自動分析每一個 MR/PR 的 diff把潛在問題、風險點、可讀性建議按優(yōu)先級整理出來讓團隊成員把有限的精力花在真正重要的討論上。這篇文章不寫廣告式的功能介紹而是把我從設(shè)計、開發(fā)到落地到團隊日常流程里的完整思路和踩坑記錄都攤開來講適合正在考慮引入自動化評審工具、或者想自己實現(xiàn)一個類似工具的開發(fā)者參考。先說背景。我所在的團隊大概三四年前開始強制推行 Code Review規(guī)則定得很細所有 MR 必須至少一人 approve、合入前必須解決所有 blocker 級評論。但制度推了一段時間之后問題反而越來越明顯。Reviewer 不是不想看是真的看不過來。一個剛重構(gòu)完的服務(wù)模塊diff 動輒上千行指望一個人在會議間隙把邏輯漏洞、并發(fā)隱患、資源泄漏全看出來根本不現(xiàn)實。更麻煩的是每個人關(guān)注的點不一樣有人盯命名和格式有人只看業(yè)務(wù)正確性同一個 MR 在不同人手里評審結(jié)果可以差很遠。后來我們內(nèi)部做過一次不完全統(tǒng)計線上故障里有接近三成和“評審時沒發(fā)現(xiàn)問題”直接相關(guān)。這個數(shù)字給我觸動很大。我要的東西很明確一個能自動讀 diff、像資深 Reviewer 一樣輸出結(jié)構(gòu)化意見、還能對問題進行分級的工具。當時找了一圈現(xiàn)成方案要么是商業(yè) SaaS代碼要出內(nèi)網(wǎng)數(shù)據(jù)安全這關(guān)過不去要么是純 Lint 工具只能查格式和基礎(chǔ)規(guī)范邏輯層面的問題完全覆蓋不到。折騰了幾天之后我決定自己寫一個定位就叫 open-code-review開源、可自托管、AI 輔助評審。下面這篇就是完整的設(shè)計思路、核心實現(xiàn)和落地過程中的真實經(jīng)驗希望能幫到同樣在做技術(shù)管理或者效能工具的同學。1. 先拆清楚需求Code Review 工具到底該解決什么問題1.1 人工評審最大的瓶頸不是態(tài)度是信息處理量很多人一提 Code Review 做不好第一反應(yīng)是團隊成員不重視、走過場。我在實際推行過程中發(fā)現(xiàn)態(tài)度問題當然有但更深層的原因是人腦處理大 diff 的能力是有明顯上限的。我觀察過一個相對健康的評審節(jié)奏當 MR 變更量在 200 行以內(nèi)時Reviewer 通常能認真看完能發(fā)現(xiàn)邏輯錯誤、邊界遺漏和潛在缺陷到 500 行左右注意力就開始下降大部分人會跳過測試文件和配置文件只盯著核心業(yè)務(wù)代碼一旦超過 1000 行基本就變成“掃一眼有沒有明顯語法錯誤然后點 approve”。這不是某一個人的問題是短期記憶和注意力資源決定了人類在密集代碼審查場景下只能維持有限的性能。我自己也一樣連續(xù)看三個大 MR 之后第四個基本就是機械操作。這和代碼評審的目標是直接沖突的。評審最重要的價值是發(fā)現(xiàn)“寫代碼時自己看不見的問題”比如并發(fā)場景下的競態(tài)、異常情況下資源沒釋放、業(yè)務(wù)流程里某個分支沒覆蓋到。這些問題恰恰藏在大 diff 和各種上下文交織的地方單靠人眼去掃漏掉是大概率的。open-code-review 首先要解決的就是把這個信息處理瓶頸用工具補上讓機器先做一輪全量掃描把可疑點挑出來人只需要在它給出的候選里做判斷和補充。1.2 標準不統(tǒng)一與知識流失是另一個隱形殺手團隊里如果有十個人經(jīng)常做 Review你很快會發(fā)現(xiàn)一個現(xiàn)象同一個改動在不同 Reviewer 眼里評估結(jié)果完全不同。有人極其在意可讀性一個命名不規(guī)范能寫三條評論有人只關(guān)心業(yè)務(wù)對不對格式問題一概不管還有人只在自己熟悉的模塊里提意見其他文件一律跳過。評審質(zhì)量高度依賴個人經(jīng)驗、當天的心情和手上的任務(wù)量。標準不統(tǒng)一帶來的不只是質(zhì)量問題還有團隊內(nèi)部的認知混亂。新人往往會困惑為什么上次說不要這么寫這次另一個 Review 又讓這么寫為什么會有人認為這個寫法可以那個人卻說不行這些困惑長年累月積累下來代碼風格越來越碎片化架構(gòu)規(guī)范形同虛設(shè)。另一個容易被忽略的問題是知識流失。Code Review 里產(chǎn)生的有效意見通常散落在 MR 的評論里幾乎沒有團隊會系統(tǒng)性地把這些問題總結(jié)成沉淀文檔。同樣的坑這個月在這個模塊踩一次下個月在另一個模塊再踩一次。open-code-review 在設(shè)計時專門加了規(guī)則引擎就是想讓沉淀這件事自動發(fā)生凡是團隊反復(fù)出現(xiàn)的典型錯誤都可以固化成規(guī)則后續(xù)每次評審自動檢查不用再靠某個人的記憶去提醒。1.3 我的產(chǎn)品定位先過濾、再分級、不替代人open-code-review 的定位用三句話可以講清楚它做第一輪過濾把所有明顯問題、可疑邏輯、規(guī)范性偏差自動列出來減少人去找問題的時間。它做問題分級不搞“一條評論打天下”而是把問題按嚴重程度分成 P0 到 P3讓 Reviewer 優(yōu)先處理高危項。它絕不替代人所有建議都是“參考意見”最終是否采納、是否合入決策權(quán)永遠在人類 Reviewer 手里。這個定位是和商業(yè)工具做過對比后確定的。當時我整理過一張對比表核心差異點如下對比維度商業(yè) SaaS 評審工具傳統(tǒng) Lint 工具open-code-review數(shù)據(jù)是否出內(nèi)網(wǎng)通常需要上傳代碼到廠商不出內(nèi)網(wǎng)完全本地自托管邏輯層面分析較強依賴廠商模型基本沒有支持可對接自建模型規(guī)則自定義受平臺限制強但范圍單一強支持層級化規(guī)則問題分級能力部分支持弱專門設(shè)計默認分級成本按席位/按用量付費免費只有模型調(diào)用成本表格里最讓我在意的其實是“數(shù)據(jù)是否出內(nèi)網(wǎng)”這一行。代碼本身就是公司最核心的資產(chǎn)很多團隊在引入外部評審工具時都會在這道關(guān)上猶豫很久。自托管方案雖然前期要花一些精力搭但數(shù)據(jù)安全這個底線是穩(wěn)的后續(xù)用起來也踏實。2. 核心模塊拆解open-code-review 到底怎么工作的2.1 diff 提取與解析高質(zhì)量評審的地基整個工具第一步不是分析代碼而是先把變更內(nèi)容準確取出來。這一步看起來簡單實際坑不少。Git 官方的 diff 格式有統(tǒng)一的標準但真要解析起來得處理 hunk header、上下文行、新增行、刪除行還要準確知道每一行在原文件和新文件里的行號否則后面想在指定行掛評論就做不到了。我最初直接用git diff --unified3拿完整 diff 文本然后扔給正則去切 hunk。后來發(fā)現(xiàn)正則解析在遇到文件名帶空格、二進制文件、重命名文件時特別容易翻車。最終改成用現(xiàn)成的解析庫來處理再對結(jié)果做一層二次加工。這里給想自己實現(xiàn)類似工具的朋友一個建議不要自己硬寫 diff 解析器除非你有大量時間折騰邊界情況直接用成熟庫把精力花在更有價值的分析邏輯上。拿到 diff 之后還有一層過濾要做。一個普通的 MR 里通?;熘罅吭胍粑募ackage-lock.json、yarn.lock、vendor目錄、生成的 proto 文件、構(gòu)建產(chǎn)物。這些文件既不適合用 AI 去分析也不值得人工去 review直接過濾掉能省一大半 token 和注意力。默認過濾規(guī)則我列在 config 里團隊可以按自己情況追加比如某些內(nèi)部工具生成的代碼目錄也可以一鍵排除。2.2 三層評審管線靜態(tài)規(guī)則、啟發(fā)式分析、大模型語義分析open-code-review 最核心的設(shè)計是三層管線每一層解決一類問題成本從低到高覆蓋面也從窄到寬。第一層是靜態(tài)規(guī)則檢查?;?Ruff 和自建的正則、AST 規(guī)則快速掃一遍 diff 里的所有文件專門抓格式問題、明顯的反模式、遺留調(diào)試代碼。這一層速度極快一個幾百行的 MR 基本在幾百毫秒內(nèi)就能跑完成本幾乎為零。規(guī)則命中率很高因為都是確定性的模式匹配基本不會誤報。第二層是啟發(fā)式分析。這一層做的是“改動點關(guān)聯(lián)推算”。比如你改動了一個函數(shù)工具會檢查這個函數(shù)的所有調(diào)用方是否也需要跟著改你新增了一個except分支工具會提醒你檢查是否吞掉了異常你在配置里改了超時時間工具會提示確認下游服務(wù)是否也有對應(yīng)調(diào)整。這類檢查不需要理解深層語義但需要對代碼結(jié)構(gòu)做索引和追蹤是純規(guī)則引擎很難覆蓋的部分。第三層才是大模型語義分析。這一層會把 diff 按文件、按函數(shù)做切片配合改動上下文的代碼片段統(tǒng)一交給大模型去分析重點找并發(fā)問題、資源泄漏、狀態(tài)一致性、邊界條件和潛在性能隱患。這一層最貴也最慢但能覆蓋前面兩層完全發(fā)現(xiàn)不了的問題。三層管線加在一起才構(gòu)成一個相對完整的評審能力。選型時我有意把大模型分析放在最后一層而不是所有 diff 都直接送 AI原因很實際成本。按一次 MR 平均 500 行變更計算如果全部丟給模型處理消耗的 token 量非常大而其中 60% 以上的文件是配置、測試、樣式類改動根本沒太多語義分析價值。先用廉價規(guī)則過濾一遍讓模型只處理真正需要“讀代碼”的部分成本和效果才能平衡。2.3 風險分級與評論結(jié)構(gòu)人工評審容易出現(xiàn)的另一個問題是評論輕重不分。有人會在格式問題上長篇大論把真正嚴重的邏輯問題帶過去。為了讓機器生成的評論更有用open-code-review 默認把所有問題分成四個等級等級含義典型例子P0必須修復(fù)阻塞合入明顯的安全問題、數(shù)據(jù)丟失風險、越權(quán)訪問P1建議修復(fù)大概率會產(chǎn)生 bug空指針風險、資源未關(guān)閉、競態(tài)條件P2值得關(guān)注可能存在問題邊界值未處理、邏輯分支遺漏、性能隱患P3風格與可讀性優(yōu)化命名不規(guī)范、魔法數(shù)字、注釋缺失分級由多個信號綜合得出靜態(tài)規(guī)則自帶等級、啟發(fā)式規(guī)則的預(yù)設(shè)等級、大模型輸出的置信度以及對關(guān)鍵風險關(guān)鍵詞的匹配。比如評論里出現(xiàn)了“資源泄漏”“死鎖”“數(shù)據(jù)不一致”這些詞并命中關(guān)鍵路徑分級會自動上調(diào)。評論的最終格式也做了固定模板每條評論包含問題描述、風險等級、具體位置、修復(fù)建議、參考示例。這樣做的好處是 Reviewer 不用再點進代碼去猜這條評論到底想表達什么掃一眼標題和等級就能決定要不要處理。機器生成的評論如果比人工還難讀那就失去了意義。2.4 與 Git 平臺對接Webhook、CI、命令行三種模式工具搭好了得接入團隊現(xiàn)有流程否則沒人記得手動跑。open-code-review 支持三種運行模式覆蓋不同團隊的習慣Webhook 模式監(jiān)聽 Git 平臺的事件推送MR/PR 創(chuàng)建或更新時自動觸發(fā)評審結(jié)果直接以評論形式回寫到對應(yīng)位置。CI 模式作為流水線中的一個 step 運行適合已經(jīng)全面 CI 化的團隊評審結(jié)果作為流水線產(chǎn)物輸出。命令行模式本地手動跑適合個人調(diào)試或者對某些敏感 MR 單獨追加評審。三種模式底層共用同一套分析邏輯只是觸發(fā)和回寫方式不同。實際落地時我推薦先跑命令行模式熟悉輸出再切成 CI 或 Webhook避免一上來就自動評論把大家嚇到。3. 實操記錄從零跑通 open-code-review3.1 部署方式與環(huán)境準備open-code-review 基于 Python 3.10安裝過程不復(fù)雜。拿到源碼之后先創(chuàng)建虛擬環(huán)境再裝依賴避免污染系統(tǒng)環(huán)境git clone https://github.com/your-org/open-code-review.git cd open-code-review python3 -m venv venv source venv/bin/activate pip install -r requirements.txt依賴裝完以后第一步是準備配置文件。項目采用單個config.yaml集中管理所有參數(shù)我把一個最小可用版本貼在這里project: name: demo-service platform: type: gitlab # github / gitlab / gitea url: https://gitlab.example.com token_env: GIT_REVIEW_TOKEN # 從環(huán)境變量讀取憑證不寫死在配置里 diff: ignore_paths: - lock.json$ - vendor/ - .pb.go$ max_file_size: 500 # 超過 500 行的單文件不做 AI 分析 rules: static: true heuristic: true enable_custom_rules: true llm: provider: openai-compatible # 兼容 OpenAI 接口即可可指向自建服務(wù) base_url: http://localhost:8000/v1 model: deepseek-v3 temperature: 0.1 max_tokens: 2000 concurrency: 4 timeout_seconds: 60 retry_times: 3這里有一個關(guān)鍵設(shè)計token 一律從環(huán)境變量讀取不落盤、不進版本庫。團隊里多人協(xié)作時每個人的憑證都走自己的環(huán)境變量避免密鑰泄露風險。3.2 本地先跑通命令行模式配置好之后建議先用命令行模式在本地試跑一次確認整條鏈路是通的export GIT_REVIEW_TOKENyour_token_here python main.py review \ --repo-path /path/to/your/repo \ --from-ref origin/main \ --to-ref feature/xxx \ --format markdown執(zhí)行后終端會輸出一份完整的評審報告包含文件清單、問題列表、分級統(tǒng)計和修復(fù)建議。第一次跑如果你的代碼質(zhì)量還不錯輸出可能會讓你覺得“就這”這其實是正常的。工具的價值在長期運行里體現(xiàn)當團隊開始持續(xù)收到“這里的資源沒釋放”“這個分支缺少空值判斷”這類提醒時它才會真正變成質(zhì)量防線的一部分。任何工具在上線前都應(yīng)該先輸出給人看而不是直接寫回平臺。命令行模式就是干這個用的批量處理一個迭代的所有 MR積累一些樣本數(shù)據(jù)再決定最終的規(guī)則組合。3.3 接入 GitHub Actions團隊用 GitHub 的話接入方式最簡單。倉庫根目錄放一個 workflow 文件即可name: code-review on: pull_request: types: [opened, synchronize] jobs: review: runs-on: ubuntu-latest steps: - uses: actions/checkoutv4 with: fetch-depth: 0 # 必須拉全量歷史否則 diff 計算會出錯 - name: Run open-code-review env: GIT_REVIEW_TOKEN: ${{ secrets.GIT_REVIEW_TOKEN }} run: | python main.py review \ --repo-path $GITHUB_WORKSPACE \ --from-ref origin/${{ github.event.pull_request.base.ref }} \ --to-ref origin/${{ github.event.pull_request.head.ref }} \ --platform github \ --post-comments true這里最容易踩的坑是fetch-depth: 0。GitHub Actions 默認只拉取最新一次提交沒有完整歷史git diff根本拿不到正確的變更范圍。這個參數(shù)我在初版 workflow 里漏掉過結(jié)果工具跑完顯示“沒有發(fā)現(xiàn)任何差異”排查了半小時才反應(yīng)過來是克隆深度的問題。3.4 接入 GitLab CIGitLab 的接入方式類似在.gitlab-ci.yml里加一個 jobcode-review: stage: test image: python:3.11-slim script: - pip install -r requirements.txt - export GIT_REVIEW_TOKEN$CI_JOB_TOKEN - python main.py review --repo-path $CI_PROJECT_DIR --from-ref origin/$CI_MERGE_REQUEST_TARGET_BRANCH_NAME --to-ref origin/$CI_COMMIT_SHA --platform gitlab --post-comments true rules: - if: $CI_PIPELINE_SOURCE merge_request_eventGitLab 這里有個細節(jié)$CI_JOB_TOKEN的權(quán)限范圍可能不夠回寫評論如果遇到權(quán)限問題需要在項目中單獨配置一個具備api權(quán)限的 token用環(huán)境變量注入。這個在下一節(jié)展開講。3.5 模型參數(shù)與成本調(diào)優(yōu)模型參數(shù)直接影響評審質(zhì)量和成本我最常用的一組配置可以作為起點參數(shù)推薦值理由temperature0.1~0.2評審場景要穩(wěn)定輸出溫度太高容易出現(xiàn)天馬行空的建議max_tokens1500~2500一次評審報告不需要太長太長反而沒人看concurrency4~8別把模型服務(wù)打滿留余量給其他業(yè)務(wù)timeout_seconds60模型接口偶爾會慢超過 60 秒直接重試更劃算成本方面做過一次粗略估算假設(shè)一個 300 行變更的 MR經(jīng)過規(guī)則過濾后真正送模型的代碼片段約 6000 token加上 prompt 模板和注釋上下文單次評審總消耗在 15000 token 左右。按目前主流模型的定價單次評審成本大約在幾毛錢級別一天 50 個 MR 也就一杯咖啡錢。這個成本換回的是統(tǒng)一的首次篩選對我來說非常值。4. 踩坑與排查實戰(zhàn)中遇到的典型問題4.1 權(quán)限問題403/404 與 token 配置接入 Git 平臺時遇到最多的問題就是權(quán)限。典型的現(xiàn)象是工具能本地跑通但一接 CI 就報 403 或 404評論寫不回去。403 大概率是 token 權(quán)限不足。GitHub 的 personal access token 需要勾選repo和pull_requests相關(guān)權(quán)限GitLab 的 token 需要勾選api權(quán)限。CI 內(nèi)置的 token 往往權(quán)限有限直接創(chuàng)建專用 token 用環(huán)境變量傳入最省事。404 則通常是 token 對應(yīng)的賬號沒有該倉庫的訪問權(quán)限檢查一下賬號是否被加入項目成員列表。這類問題在本地永遠不會出現(xiàn)因為本地開發(fā)賬號權(quán)限完整。所以排查權(quán)限問題時第一件事不是在代碼里找 bug而是確認 CI 環(huán)境里實際生效的 token 到底是什么、有哪些權(quán)限。我一般會在 CI 腳本里臨時加一行輸出當前用戶信息確認身份后再逐步排查。4.2 誤報太多怎么辦噪音控制是工具能長期用的關(guān)鍵工具剛上線那段時間最常見的反饋是“評論太吵了”。一堆 P3 級的備注密密麻麻貼在 MR 里真正有用的問題反而被淹沒。這個問題處理不好工具就會從輔助變成負擔最后被大家吐槽到關(guān)停。我逐步摸索出幾條控制噪音的策略。第一設(shè)置評論門檻默認只回寫 P1 及以上的問題P2、P3 只在輸出報告里展示。第二增加去重機制同一類問題在同一文件里只保留一條代表性評論避免十條一模一樣的空指針提醒。第三維護 ignore 路徑和規(guī)則白名單某些歷史包袱較重的文件不啟用部分規(guī)則等團隊有空重構(gòu)了再放開。最后每兩周復(fù)盤一次所有誤報反饋把重復(fù)出現(xiàn)的無效規(guī)則直接下線或者調(diào)低等級。誤報無法完全消除但可以把傷害降到最低。工具的價值在于幫人省時間如果因為噪音過多讓人產(chǎn)生抵觸心理再準的規(guī)則也白搭。4.3 大模型接口限流、超時與失敗重試模型服務(wù)的穩(wěn)定性是另一個容易翻車的點。線上環(huán)境偶爾會遇到接口限流、超時或者返回格式不合法的情況。open-code-review 里做了三層防護指數(shù)退避重試、并發(fā)限流和失敗降級。重試使用指數(shù)退避第一次失敗等 1 秒第二次 2 秒第三次 4 秒最多重試三次。超過次數(shù)后當前分析任務(wù)標記為“跳過并記錄”不會讓整個 MR 的評審流程卡死。并發(fā)限流則是通過配置里的concurrency參數(shù)控制同時發(fā)送的請求數(shù)量防止把模型服務(wù)打爆。核心思路是評審工具必須“可用”優(yōu)先級高于“全面”偶爾漏掉一次分析比整個 MR 阻塞在評審環(huán)節(jié)要好得多。4.4 大 diff 與上下文超限的處理實際開發(fā)中一個 MR 改幾個大文件的情況非常常見。如果直接把整個文件內(nèi)容都塞給模型很容易超出上下文窗口。open-code-review 的做法是先按函數(shù)切分解析 diff 涉及的每個函數(shù)只把函數(shù)體和相關(guān)上下文作為分析單元超過單文件行數(shù)上限的文件直接跳過 AI 分析只跑前面的規(guī)則檢查。這樣既保證了分析的粒度也控制了 token 消耗。當然這種策略的問題是跨文件、跨函數(shù)的全局性問題可能看漏。后續(xù)計劃加入一次全局分析只負責掃描跨文件的影響面和基于函數(shù)的細粒度分析互補。4.5 自定義規(guī)則與本地擴展團隊內(nèi)部總有工具默認規(guī)則覆蓋不到的場景所以自定義規(guī)則能力從一開始就是剛需。open-code-review 的規(guī)則引擎支持以 Python 函數(shù)方式擴展一個簡單的自定義規(guī)則長這樣# rules/custom_rules.py import re def no_todo_without_owner(content: str, file_path: str) - list: issues [] for line_no, line in enumerate(content.splitlines(), 1): if re.search(rTODO(?!\(.*), line): issues.append({ severity: P2, line: line_no, message: TODO 注釋建議標注負責人, suggestion: 寫成 TODO(username): 具體事項 }) return issues這個規(guī)則檢查的是“代碼里出現(xiàn) TODO 但沒有標注負責人”團隊可以根據(jù)自己的協(xié)作規(guī)范隨意添加。規(guī)則寫得多了以后你會發(fā)現(xiàn)它其實變成了團隊規(guī)范的活文檔新人通過這批規(guī)則的執(zhí)行能直接理解團隊約定俗成的代碼習慣。5. 一些落地體會和后續(xù)擴展5.1 工具對團隊流程的真實影響open-code-review 在團隊里穩(wěn)定跑了三個多月之后我統(tǒng)計過兩組數(shù)據(jù)單個 MR 的平均評審時間從原來的 4~5 小時縮短到 2 小時左右合入后線上問題的發(fā)現(xiàn)率有小幅提升但更明顯的變化是Reviewer 提的評論質(zhì)量變高了。以前大家會有意無意地去挑格式問題湊評論數(shù)現(xiàn)在機器把基礎(chǔ)問題都攔掉了人工評論基本集中在了業(yè)務(wù)邏輯、架構(gòu)取舍這些真正需要人類判斷的點上。這里必須強調(diào)一點工具再準也只是輔助。它最大的價值是幫團隊把低價值、確定性強的檢查自動化把人的時間和注意力釋放出來。真正有經(jīng)驗的評審討論比如這個模塊該不該這么拆分、這個接口設(shè)計是否合理機器目前還做不了也不應(yīng)該指望它做。所以團隊流程上我一直堅持一個原則工具報告可以自動跑但合入決策永遠保留給人工 Reviewer。5.2 后續(xù)想做的方向目前已經(jīng)在規(guī)劃的幾個方向一個是多語言支持當前重點在 Python 和 Go后續(xù)考慮接入 Java、TypeScript另一個是評審質(zhì)量指標看板把每個 MR 的工具發(fā)現(xiàn)率、誤報率、人工采納率記錄下來持續(xù)調(diào)優(yōu)規(guī)則權(quán)重還有一個是和內(nèi)部知識庫聯(lián)動把評審中反復(fù)出現(xiàn)的典型問題自動關(guān)聯(lián)到對應(yīng)的規(guī)范文檔。這個項目我會一直維護下去因為它在實際幫團隊省時間這件事上確實有效。如果你也在為自己的團隊琢磨類似的工具直接拿這套思路去用就行能少踩不少我踩過的坑。