有時候寫出的程式碼變得複雜、難以理解,並非因為技術不足,而是我們追求了錯誤的目標——忽略了軟體的根本目的:解決眼前的實際問題。
實用主義,讓程式碼回歸本質
我們的主要任務其實很單純:用穩定、高效的程式碼,解決實際場景的問題。
一個在理論上看似完美的設計,如果在實踐中帶來了不必要的複雜性,反而可能成為團隊的負擔,也就是我們常說的「技術債」。
我們用了多少設計模式、架構圖畫得多麼漂亮,這些都很棒,但更重要的是:我們有沒有用最簡單、最合適的方式解決眼前的問題?
來看一個常見的情境,這可能發生在任何人的專案中。
🔴 一個可能過度設計的選擇
假設團隊要開發一個新的部落格平台,預期初期使用者並不多。
這時,有夥伴提議:「我們用微服務架構吧!獨立部署、故障隔離、未來擴展性超強!」這聽起來確實很吸引人。
於是,可能會設計出這樣的微服務架構:
// 一個功能強大,但也許過於複雜的設計
class ApiGateway {
// ... 需要服務發現、配置管理、熔斷、監控等一系列機制 ...
async getPostWithComments(postId) {
// 為了組合資料,我們需要處理網路延遲、數據一致性、部分失敗等問題
// 這相當於為了一個相對簡單的功能,引入了整個分散式系統的複雜度
const post = await this.postService.fetchPost(postId);
const comments = await this.commentService.fetchCommentsForPost(postId);
const author = await this.userService.fetchUser(post.authorId);
// ...
}
}
預設了一個「未來可能發生」的問題,在專案初期就付出了極高的複雜性代價。
拖慢了開發速度,也讓後續的維護變得更加困難。
🟢 一個更具品味的選擇
那有經驗、具備好品味的工程師會怎麼做呢?
他可能會選擇最直接、最穩健的方式,從單體應用開始。
// 簡單、直接、有效,同時保持了良好的模組邊界
class BlogController {
constructor(postService, commentService, userService) {
this.postService = postService;
this.commentService = commentService;
this.userService = userService;
}
async getPostWithComments(postId) {
// 儘管都在同一個應用中,但模組職責清晰
// postService 不會直接碰觸 comment 的資料庫
const post = await this.postService.findPost(postId);
const comments = await this.commentService.findCommentsForPost(postId);
const author = await this.userService.findUser(post.authorId);
return { ...post, author, comments };
}
}
這個方案或許第一眼看起來不那麼「亮眼」,但它非常務實,通過服務(Service)層的劃分,在單體內部預先建立了清晰的模組邊界。
它乾淨、直接,讓團隊的每個人都能輕易上手,開發、測試和部署的效率都高得多。
只要從一開始就用有品味的方式寫程式,當未來流量真的成長到需要擴展時,才有再來「重構或拆分的權利」。
任何為了「未來可能的需求」而增加的抽象層或 if/else
,都可能成為日後的維護負擔。
職責是專注解決當下的問題,而不是預測未來,增加複雜性。
// 🔴 為假想問題設計的錯誤處理
class OverEngineeredErrorHandler {
handle(error, context) {
// 為了應對幾十種幾乎不會發生的錯誤場景,寫了複雜的策略...
}
}
// 🟢 專注於解決實際問題
function handleError(error) {
console.error(`[Error] ${error.stack}`);
// 如果發生了真正嚴重、需要人為介入的錯誤,再發出警報
if (error.isCritical) {
sendAlertToOpsTeam('Critical failure!');
process.exit(1); // 在某些情境下,儘快失敗重啟是個好策略
}
}
深層的巢狀結構通常是個警訊,它可能意味著函式的職責過於複雜,或是資料結構設計得不夠理想。
與其繼續增加縮排,不如回頭重新思考一下設計,看看是否能讓流程更清晰。
一個在科學資料集上表現完美的演算法,如果無法處理實際情況中混亂、不完美的數據,那它的價值就非常有限。
我們首先應該關心的是:程式碼是否足夠健壯?行為是否可預測?
以及在遇到非預期狀況時,它懂得如何優雅降級 (Graceful Degradation),而不是讓使用者面對一個崩潰的畫面。
提升程式碼品質,不在於你背下哪些設計模式,而在於內化一種務實、簡潔的開發品味。
當理論與實踐產生衝突時,永遠優先考慮實踐的有效性。
所以,下次在 Code Review 看到有人提出過於複雜的設計時,別不好意思,直接告訴他:
「這個太複雜了,用更簡單的方法來做。」
好的程式碼,是為了解決使用者的問題而生,而不是為了展現工程師的技巧。
我們要寫的是那種三個月後的自己、團隊的新夥伴都能一眼看懂的程式碼,這才是真正厲害的地方。