重構藝術 | 如何優雅地“提煉函數“

在工作中總數遇到非常多的長代碼,俗稱“屎山”,這類代碼讀起來特別費勁。自己想重構一遍,但是總感覺缺乏經驗指導,因此,多讀書,讀好書可能是最優解之一。讀《重構改善即有代碼的設計》有感,便寫下此篇博客,積累經驗!

在軟件開發的浩瀚星河中,函數是最基本的代碼單元。當我們面對臃腫冗長的函數時,《重構》一書給出的第一劑良方便是"提煉函數"。這個看似簡單的重構手法,實則是提升代碼質量的關鍵轉折點。

一、重構動機:代碼的詩意重構

當函數膨脹到需要滾動三屏才能讀完時,它就變成了代碼的"黑洞"——既吞噬可讀性,又掩蓋復用價值。更致命的是,這樣的函數往往混雜著多個抽象層級,就像把說明書、操作手冊和維修指南揉成一團。提煉函數的本質,是在混沌中建立秩序,讓每個函數都成為一首表達清晰意圖的代碼詩。

二、長度迷思:質量的新度量衡

傳統認知中,20行是函數長度的黃金分割點。但Martin Fowler給出了更深刻的見解:函數名稱與函數本體之間的語義距離才是核心標準。一個命名精準的函數,即使略長,只要每個代碼塊都在同一抽象層呼吸,就值得保留。就像好的文學作品,章節長短不重要,重要的是思想的連貫性。

三、重構四部曲

  1. 命名即設計:如同給新生兒取名,新函數的名字要能完整表達其使命。例如"計算稅費"比"處理數據"更直指本質
  2. 安全過渡:通過復制粘貼建立新函數的雛形,保留原始函數的執行流程
  3. 參數手術:識別需要傳遞的局部變量,像外科醫生般精確處理;具體情況參考下面的處理方案對照表。
  4. 替換儀式:將原函數中的代碼塊替換為對新函數的調用,完成重構的最后一舞

參數處理方案對照表

參數類型特征描述解決方案代碼示例片段
無參數被提取代碼塊不依賴任何外部變量直接提取為無參數函數function newFunc() { /* 原代碼塊 */ }
只讀參數原代碼塊讀取但不會修改外部變量將變量作為參數傳入新函數function newFunc(readVar) { /* 使用readVar */ }
可修改參數原代碼塊會修改外部變量1. 傳入參數并返回修改后的值
2. 直接修改傳入的對象屬性
function newFunc(input) { return input + 1; }
function update(obj) { obj.value++ }
共享參數原函數和提取函數共同修改同一變量1. 通過返回值更新變量
2. 使用引用類型參數
3. 封裝為對象操作
value = modify(value);
modifyInPlace(&value);
container.updateValue();
多參數混合同時包含只讀和可修改參數組合使用上述策略:
- 只讀參數直接傳入
- 可修改參數通過返回值/引用
function calc(readOnly, &output) {return readOnly}

四、復雜場景破局之道

當遇到多返回值困境時,解決方案如月光穿透迷霧:

  1. 構建臨時對象封裝多個返回值
  2. 改用集合類型(數組/元組)打包數據
  3. 重新審視函數職責,拆分為更細粒度的函數
  4. 在支持語言中利用元組解構等語法糖
// 重構前
function printOwing(invoice) {let outstanding = 0;console.log("***********************");console.log("**** Customer Owes ****");console.log("***********************");// 計算未結金額for (const o of invoice.orders) {outstanding += o.amount;}// 記錄到期日const today = Clock.today;invoice.dueDate = new Date(today.getFullYear(), today.getMonth(), today.getDate() + 30);// 打印詳情console.log(`name: ${invoice.customer}`);console.log(`amount: ${outstanding}`);console.log(`due: ${invoice.dueDate.toLocaleDateString()}`);
}// 重構后
function printOwing(invoice) {printBanner();const outstanding = calculateOutstanding(invoice);recordDueDate(invoice);printDetails(invoice, outstanding);
}

五、重構哲學:在秩序與混沌之間

提煉函數不是簡單的代碼搬家,而是一場思維革命。每個提煉動作都應使代碼更接近"自解釋文檔"的理想狀態。當函數名能準確傳達意圖,當參數列表清晰描繪輸入輸出,當每個函數都保持單一職責,代碼就會自然生長出優雅的形態。

重構大師的終極追求,是讓代碼像散文般流暢,如數學公式般精確。當我們用提煉函數的手法雕刻代碼時,其實也在雕刻自己的思維——將混沌的靈感,淬煉成精妙的藝術。

本文來自互聯網用戶投稿,該文觀點僅代表作者本人,不代表本站立場。本站僅提供信息存儲空間服務,不擁有所有權,不承擔相關法律責任。
如若轉載,請注明出處:http://www.pswp.cn/bicheng/76627.shtml
繁體地址,請注明出處:http://hk.pswp.cn/bicheng/76627.shtml
英文地址,請注明出處:http://en.pswp.cn/bicheng/76627.shtml

如若內容造成侵權/違法違規/事實不符,請聯系多彩編程網進行投訴反饋email:809451989@qq.com,一經查實,立即刪除!

相關文章

每天學一個 Linux 命令(13):touch

Linux 文件管理命令:touch touch 是 Linux 中一個簡單但高頻使用的命令,主要用于創建空文件或修改文件的時間戳(訪問時間、修改時間)。它是文件管理和腳本操作的實用工具。 1. 命令作用 創建空文件:快速生成一個或多個空白文件。更新時間戳:修改文件的訪問時間(Access …

STM32HAL庫學習筆記

目錄 定時器 一些小細節 輸入捕獲計算信號頻率 輸入捕獲計算占空比與頻率 使用定時器不改變占空比的同時改變頻率的方法 串口 重定向原理 重定向代碼 怎么從串口接收到的字符串數據中解析出float型的數據 strchr sscanf memset 第一種實現方法 RTC實時時鐘 LCD顯…

Docker 鏡像、容器與數據卷的高效管理:最佳實踐與自動化腳本20250411

Docker 鏡像、容器與數據卷的高效管理:最佳實踐與自動化腳本 引言 在現代軟件開發中,容器化技術正變得越來越重要。Docker 作為容器化的代表工具,在各大企業中得到了廣泛的應用。然而,隨著容器化應用的增多,如何高效…

Selenium之Actions事件

鼠標、鍵盤組合鍵 在使用selenium的時候,有的時候我們需要鼠標單擊、雙擊、拖動;或者是按下鍵盤的某個鍵,松開某個按鍵,以及組合鍵的使用;今天我們就來看一看,怎么樣實現上面的操作 先把準備工作做好&…

如何在 CentOS 7 系統上以容器方式部署 GitLab,使用 ZeroNews 通過互聯網訪問 GitLab 私有倉庫,進行代碼版本發布與更新

第 1 步: 部署 GitLab 容器? 在開始部署 GitLab 容器之前,您需要創建本地目錄來存儲 GitLab 數據、配置和日志: #創建本地目錄 mkdir -p /opt/docker/gitlab/data mkdir -p /opt/docker/gitlab/config mkdir -p /opt/docker/gitlab/log#gi…

.py文件和.ipynb文件的區別:完整教程

一、概述 Python開發者常用的兩種文件格式.py和.ipynb各有特點,本教程將通過對比分析、代碼示例和場景說明,幫助開發者全面理解二者的區別與聯系。 二、核心區別對比 1. 文件格式本質 特性.ipynb文件.py文件文件類型JSON結構化文檔純文本文件存儲內容…

Go 字符串四種拼接方式的性能對比

簡介 使用完整的基準測試代碼文件,可以直接運行來比較四種字符串拼接方法的性能。 for 索引 的方式 for range 的方式 strings.Join 的方式 strings.Builder 的方式 寫一個基準測試文件 echo_bench_test.go package mainimport ("os""stri…

從代碼學習深度學習 - Bahdanau注意力 PyTorch版

文章目錄 1. 前言為什么選擇Bahdanau注意力本文目標與預備知識2. Bahdanau注意力機制概述注意力機制簡述加性注意力與乘性注意力對比Bahdanau注意力的數學原理與流程圖數學原理流程圖可視化與直觀理解3. 數據準備與預處理數據集簡介數據加載與預處理1. 讀取數據集2. 預處理文本…

19【動手學深度學習】卷積層

1. 從全連接到卷積 2. 圖像卷積 3. 圖形卷積代碼 互相關操作 import torch from torch import nn from d2l import torch as d2ldef corr2d(X, K):"""計算2維互相關運算"""h, w K.shapeY torch.zeros((X.shape[0]-h1, X.shape[1]-w 1))for …

Linux xorg-server 解析(一)- 編譯安裝Debug版本的xorg-server

一:下載代碼 1. 配置源,以Ubuntu24.04 為例( /etc/apt/sources.list.d/ubuntu.sources): 2. apt source xserver-xorg-core 二:編譯代碼 1. sudo apt build-dep ./ 2. DEB_BUILD_OPTIONS="nostrip" DEB_CFLAGS_SET="-g -O0" dpkg-buildpac…

大模型SFT用chat版還是base版 SFT后災難性遺忘怎么辦

大模型SFT用chat版還是base版 進行 SFT 時,基座模型選用 Chat 還是 Base 模型? 選 Base 還是 Chat 模型,首先先熟悉 Base 和 Chat 是兩種不同的大模型,它們在訓練數據、應用場景和模型特性上有所區別。 在訓練數據方面&#xf…

【圖像生成之21】融合了Transformer與Diffusion,Meta新作Transfusion實現圖像與語言大一統

論文:Transfusion: Predict the Next Token and Diffuse Images with One Multi-Modal Model 地址:https://arxiv.org/abs/2408.11039 類型:理解與生成 Transfusion模型?是一種將Transformer和Diffusion模型融合的多模態模型,旨…

動態多目標進化算法:基于知識轉移和維護功能的動態多目標進化算法(KTM-DMOEA)求解CEC2018(DF1-DF14)

一、KTM-DMOEA介紹 在實際工程和現實生活中,許多優化問題具有動態性和多目標性,即目標函數會隨著環境的變化而改變,并且存在多個相互沖突的目標。傳統的多目標進化算法在處理這類動態問題時面臨著一些挑戰,如收斂速度慢、難以跟蹤…

部署NFS版StorageClass(存儲類)

部署NFS版StorageClass存儲類 NFS版PV動態供給StorageClass(存儲類)基于NFS實現動態供應下載NFS存儲類資源清單部署NFS服務器為StorageClass(存儲類)創建所需的RBAC部署nfs-client-provisioner的deployment創建StorageClass使用存儲類創建PVC NFS版PV動態供給StorageClass(存儲…

Vue使用el-table給每一行數據上面增加一行自定義合并行

// template <template><el-table:data"flattenedData":span-method"objectSpanMethod"borderclass"custom-header-table"style"width: 100%"ref"myTable":height"60vh"><!-- 訂單詳情列 -->&l…

vue項目使用html2canvas和jspdf將頁面導出成PDF文件

一、需求&#xff1a; 頁面上某一部分內容需要生成pdf并下載 二、技術方案&#xff1a; 使用html2canvas和jsPDF插件 三、js代碼 // 頁面導出為pdf格式 import html2Canvas from "html2canvas"; import jsPDF from "jspdf"; import { uploadImg } f…

大模型LLM表格報表分析:markitdown文件轉markdown,大模型markdown統計分析

整體流程&#xff1a;用markitdown工具文件轉markdown&#xff0c;然后大模型markdown統計分析 markitdown https://github.com/microsoft/markitdown 在線體驗&#xff1a;https://huggingface.co/spaces/AlirezaF138/Markitdown 安裝&#xff1a; pip install markitdown…

Linux 第二講 --- 基礎指令(二)

前言 這是基礎指令的第二部分&#xff0c;但是該部分的講解會大量使用到基礎指令&#xff08;一&#xff09;的內容&#xff0c;為了大家的觀感&#xff0c;如果對Linux的一些基本指令不了解的話&#xff0c;可以先看基礎指令&#xff08;一&#xff09;&#xff0c;同樣的本文…

python格式化字符串漏洞

什么是python格式化字符串漏洞 python中&#xff0c;存在幾種格式化字符串的方式&#xff0c;然而當我們使用的方式不正確的時候&#xff0c;即格式化的字符串能夠被我們控制時&#xff0c;就會導致一些嚴重的問題&#xff0c;比如獲取敏感信息 python常見的格式化字符串 百…

LLaMA-Factory雙卡4090微調DeepSeek-R1-Distill-Qwen-14B醫學領域

unsloth單卡4090微調DeepSeek-R1-Distill-Qwen-14B醫學領域后&#xff0c;跑通一下多卡微調。 1&#xff0c;準備2卡RTX 4090 2&#xff0c;準備數據集 醫學領域 pip install -U huggingface_hub export HF_ENDPOINThttps://hf-mirror.com huggingface-cli download --resum…