详细介绍优化函数的构成
下面介绍了几种优化函数:
1. Extract Method (提炼函数)
解释:
如果发现一个函数的代码很长, 很可能的一种情况是这个函数做了很多事情, 找找看函数中有没有注释, 往往注释都是为了解释下面一块代码做的什么事情, 可以考虑将这块代码提炼(Extract)成一个独立的函数.
这样做的好处不言而喻, 是面向对象五大基本原则中的单一职责原则 (Single Responsibility Principle), 比较长的函数被拆分成一个个小函数, 将有利于代码被复用.
冲动前:
<ol class="dp-c"> <li class="alt"><span><span class="keyword">public</span><span> void Print(Employee employee) </span></span></li> <li><span>{ </span></li> <li class="alt"> <span class="comment">//print employee's information </span><span> </span> </li> <li> <span>Console.WriteLine(</span><span class="string">"Name:"</span><span> + employee.Name); </span> </li> <li class="alt"> <span>Console.WriteLine(</span><span class="string">"Sex:"</span><span> + employee.Sex); </span> </li> <li> <span>Console.WriteLine(</span><span class="string">"Age:"</span><span> + employee.Age); </span> </li> <li class="alt"> <span class="comment">//print employee's salary </span><span> </span> </li> <li> <span>Console.WriteLine(</span><span class="string">"Salary:"</span><span> + employee.Salary); </span> </li> <li class="alt"> <span>Console.WriteLine(</span><span class="string">"Bonus:"</span><span> + employee.Bonus); </span> </li> <li><span>} </span></li> </ol>
冲动后:
<ol class="dp-c"> <li class="alt"><span><span class="keyword">public</span><span> void Print(Employee employee) </span></span></li> <li><span>{ </span></li> <li class="alt"> <span class="comment">//print employee's information </span><span> </span> </li> <li><span>PrintInfo(employee); </span></li> <li class="alt"> <span class="comment">//print employee's salary </span><span> </span> </li> <li><span>PrintSalary(employee); </span></li> <li class="alt"><span>} </span></li> <li> <span class="keyword">public</span><span> void PrintInfo(Employee employee) </span> </li> <li class="alt"><span>{ </span></li> <li> <span>Console.WriteLine(</span><span class="string">"Name:"</span><span> + employee.Name); </span> </li> <li class="alt"> <span>Console.WriteLine(</span><span class="string">"Sex:"</span><span> + employee.Sex); </span> </li> <li> <span>Console.WriteLine(</span><span class="string">"Age:"</span><span> + employee.Age); </span> </li> <li class="alt"><span>} </span></li> <li> <span class="keyword">public</span><span> void PrintSalary(Employee employee) </span> </li> <li class="alt"><span>{ </span></li> <li> <span>Console.WriteLine(</span><span class="string">"Salary:"</span><span> + employee.Salary); </span> </li> <li class="alt"> <span>Console.WriteLine(</span><span class="string">"Bonus:"</span><span> + employee.Bonus); </span> </li> <li><span>} </span></li> </ol>
2. Inline Method (将函数内联)
解释:
有些函数很短, 只有一两行, 而且代码的意图也非常明显, 这时可以考虑将这个函数干掉, 直接使用函数中的代码.物件中过多的方法会让人感到不舒服, 干掉完全不必要的函数后代码会更简洁.
冲动前:
<ol class="dp-c"> <li class="alt"><span><span class="keyword">public</span><span> bool IsDeserving(int score) </span></span></li> <li><span>{ </span></li> <li class="alt"> <span class="keyword">return</span><span> IsScoreMoreThanSixty(score); </span> </li> <li><span>} </span></li> <li class="alt"> <span class="keyword">public</span><span> bool IsScoreMoreThanSixty(int score) </span> </li> <li><span>{ </span></li> <li class="alt"> <span class="keyword">return</span><span> (score > 60); </span> </li> <li><span>} </span></li> </ol>
冲动后:
<ol class="dp-c"> <li class="alt"><span><span class="keyword">public</span><span> bool IsDeserving(int score) </span></span></li> <li><span>{ </span></li> <li class="alt"> <span class="keyword">return</span><span> (score > 60) ; </span> </li> <li><span>} </span></li> </ol>
3. Inline Temp (将临时变量内联)
解释:
如果有一个临时变量 (Temp)用来表示某个函数的返回值, 一般来说, 这样的做法挺好的. 但如果这个临时变量实在多余, 将这个临时变量内联之后毫不影响代码的阅读, 甚至这个临时变量妨碍了其它重构工作, 就应该将这个临时变量内联化.
把这个临时变量干掉的好处在于减少了函数的长度, 有时可以让其它重构工作更顺利的进行.
冲动前:
<ol class="dp-c"> <li class="alt"><span><span>int salary = employee.Salary; </span></span></li> <li> <span class="keyword">return</span><span> (salary > 10000); </span> </li> </ol>
冲动后:
<ol class="dp-c"> <li class="alt"><span><span class="keyword">return</span><span> (employee.Salary > 10000); </span></span></li> <li><span>Replace Temp With Query (用查询式代替临时变量) </span></li> </ol>
解释:
程序中有一个临时变量(Temp)用来保存某个表达式的计算结果, 将这个计算表达式提炼(Extract)到一个独立的函数(即查询式Query)中, 将这个临时变量所有被调用的地方换成对新函数(Query)的调用, 新函数还可以被其它函数使用.
好处在于减少函数长度, 增加代码复用率, 有利于代码进一步的重构. 并且注意 Replace Temp With Query 往往是 Extract Method 之前必不可少的步骤, 因为局部变量会使代码不太容易被提炼, 所以在进行类似的重构前可以将它们替换成查询式.
下面的这个例子不是很有必要使用Replace Temp With Query, 主要展示如何 Replace Temp With Query. 试想"冲动前"函数中有很多个代码块都使用到 totalPrice, 突然有一天我发现这个函数太长, 我需要将这一块块的代码提炼成单独的函数, 这样就需要将 totalPrice = price * num; 放到每一个提炼出来的函数中. 而如果原来函数中使用的是查询式, 就不存在这个问题. 如果查询式中的计算量很大, 也不建议使用 Replace Temp With Query.
冲动前:
<ol class="dp-c"> <li class="alt"><span><span class="keyword">public</span><span> double FinalPrice(double price, int num) </span></span></li> <li><span>{ </span></li> <li class="alt"><span>double totalPrice = price * num; </span></li> <li> <span class="keyword">if</span><span> (totalPrice > 100) </span> </li> <li class="alt"> <span class="keyword">return</span><span> totalPrice * 0.8; </span> </li> <li> <span class="keyword">else</span><span> </span> </li> <li class="alt"> <span class="keyword">return</span><span> totalPrice * 0.9; </span> </li> <li><span>} </span></li> </ol>
冲动后:
<ol class="dp-c"> <li class="alt"><span><span class="keyword">public</span><span> double FinalPrice(double price, int num) </span></span></li> <li><span>{ </span></li> <li class="alt"> <span class="keyword">if</span><span> (TotalPrice(price, num) > 100) </span> </li> <li> <span class="keyword">return</span><span> TotalPrice(price, num) * 0.8; </span> </li> <li class="alt"> <span class="keyword">else</span><span> </span> </li> <li> <span class="keyword">return</span><span> TotalPrice(price, num) * 0.9; </span> </li> <li class="alt"><span>} </span></li> <li> <span class="keyword">public</span><span> double TotalPrice(double price, int num) </span> </li> <li class="alt"><span>{ </span></li> <li> <span class="keyword">return</span><span> price * num; </span> </li> <li class="alt"><span>} </span></li> </ol>
5. Introduce Explaining Variable (引入可以理解的变量)
解释:
很多时候在条件逻辑表达式中, 很多条件令人难以理解它的意义, 为什么要满足这个条件? 不清楚. 可以使用Introduce Explaining Variable将每个条件子句提炼出来, 分别用一个恰当的临时变量名表示条件子句的意义.
好处在于增加了程序的可读性.
冲动前:
<ol class="dp-c"> <li class="alt"><span><span class="keyword">if</span><span>((operateSystem.Contains(</span><span class="string">"Windows"</span><span>))&& (browser.Contatins(</span><span class="string">"IE"</span><span>))) </span></span></li> <li><span>{ </span></li> <li class="alt"> <span> </span><span class="comment">//do something </span><span> </span> </li> <li><span>} </span></li> </ol>
冲动后:
<ol class="dp-c"> <li class="alt"><span><span>bool isWindowsOS = operateSystem.Contains(</span><span class="string">"Windows"</span><span>); </span></span></li> <li> <span>bool isIEBrowser = browser.Contatins(</span><span class="string">"IE"</span><span>); </span> </li> <li class="alt"> <span class="keyword">if</span><span> (isWindowsOS && isIEBrowser) </span> </li> <li><span>{ </span></li> <li class="alt"> <span class="comment">//do something </span><span> </span> </li> <li><span>} </span></li> </ol>
6. Split Temporary Variable (撇清临时变量)
解释:
例如代码中有个临时变量在函数上面某处表示长方形周长, 在函数下面被赋予面积, 也就是这个临时变量被赋值超过一次, 且表示的不是同一种量. 应该针对每次赋值, 分配一个独立的临时变量.
一个变量只应表示一种量, 否则会令代码阅读者感到迷惑.
冲动前:
<ol class="dp-c"> <li class="alt"><span><span>double temp = (width + height) * 2; </span></span></li> <li> <span class="comment">//do something </span><span> </span> </li> <li class="alt"><span>temp = width * height; </span></li> <li> <span class="comment">//do something </span><span> </span> </li> </ol>
冲动后:
<ol class="dp-c"> <li class="alt"><span><span>double perimeter = (width + height) * 2; </span></span></li> <li> <span class="comment">//do something </span><span> </span> </li> <li class="alt"><span>double area = width * height; </span></li> <li> <span class="comment">//do something </span><span> </span> </li> </ol>
7. Remove Assignments to Parameters (消除对参数的赋值操作)
解释:
传入参数分"传值"和"传址"两种, 如果是"传址", 在函数中改变参数的值无可厚非, 因为我们就是想改变原来的值. 但如果是"传值", 在代码中为参数赋值, 就会令人产生疑惑. 所以在函数中应该用一个临时变量代替这个参数, 然后对这个临时变量进行其它赋值操作.
冲动前:
<ol class="dp-c"> <li class="alt"><span><span class="keyword">public</span><span> double FinalPrice(double price, int num) </span></span></li> <li><span>{ </span></li> <li class="alt"><span>price = price * num; </span></li> <li> <span class="comment">//other calculation with price </span><span> </span> </li> <li class="alt"> <span class="keyword">return</span><span> price; </span> </li> <li><span>} </span></li> </ol>
冲动后:
<ol class="dp-c"> <li class="alt"><span><span class="keyword">public</span><span> double FinalPrice(double price, int num) </span></span></li> <li><span>{ </span></li> <li class="alt"><span>double finalPrice = price * num; </span></li> <li> <span class="comment">//other calculation with finalPrice </span><span> </span> </li> <li class="alt"> <span class="keyword">return</span><span> finalPrice; </span> </li> <li><span>} </span></li> </ol>
8. Replace Method with Method Object (用函数物件代替函数)
解释:
冲动的写下一行行代码后, 突然发现这个函数变得非常大, 而且由于这个函数包含了很多局部变量, 使得无法使用 Extract Method, 这时 Replace Method with Method Object 就起到了杀手锏的效果. 做法是将这个函数放入一个单独的物件中, 函数中的临时变量就变成了这个物件里的值域 (field).
冲动前:
<ol class="dp-c"> <li class="alt"><span><span class="keyword">class</span><span> Bill </span></span></li> <li><span>{ </span></li> <li class="alt"> <span class="keyword">public</span><span> double FinalPrice() </span> </li> <li><span>{ </span></li> <li class="alt"><span>double primaryPrice; </span></li> <li><span>double secondaryPrice; </span></li> <li class="alt"><span>double teriaryPrice; </span></li> <li> <span class="comment">//long computation </span><span> </span> </li> <li class="alt"><span>... </span></li> <li><span>} </span></li> <li class="alt"><span>} </span></li> </ol>
冲动后:
<ol class="dp-c"> <li class="alt"><span><span class="keyword">class</span><span> Bill </span></span></li> <li><span>{ </span></li> <li class="alt"> <span class="keyword">public</span><span> double FinalPrice() </span> </li> <li><span>{ </span></li> <li class="alt"> <span class="keyword">return</span><span> </span><span class="keyword">new</span><span> PriceCalculator(this).compute(); </span> </li> <li><span>} </span></li> <li class="alt"><span>} </span></li> <li> <span class="keyword">class</span><span> PriceCalculator </span> </li> <li class="alt"><span>{ </span></li> <li><span>double primaryPrice; </span></li> <li class="alt"><span>double secondaryPrice; </span></li> <li><span>double teriaryPrice; </span></li> <li class="alt"> <span class="keyword">public</span><span> PriceCalculator(Bill bill) </span> </li> <li><span>{ </span></li> <li class="alt"> <span class="comment">//initial </span><span> </span> </li> <li><span>} </span></li> <li class="alt"> <span class="keyword">public</span><span> double compute() </span> </li> <li><span>{ </span></li> <li class="alt"> <span class="comment">//computation </span><span> </span> </li> <li><span>} </span></li> <li class="alt"><span>} </span></li> </ol>
9. Substitute Algorithm (替换算法)
解释:
有这么一个笑话:
某跨国日化公司, 肥皂生产线存在包装时可能漏包肥皂的问题, 肯定不能把空的肥皂盒卖给顾客, 于是该公司总裁命令组成了以博士牵头的专家组对这个问题进行攻关, 该研发团队使用了世界上最高精尖的技术 (如红外探测, 激光照射等), 在花费了大量美金和半年的时间后终于完成了肥皂盒检测系统, 探测到空的肥皂盒以后, 机械手会将空盒推出去. 这一办法将肥皂盒空填率有效降低至5%以内, 问题基本解决.
而某乡镇肥皂企业也遇到类似问题, 老板命令初中毕业的流水线工头想办法解决之, 经过半天的思考, 该工头拿了一台电扇到生产线的末端对着传送带猛吹, 那些没有装填肥皂的肥皂盒由于重量轻就都被风吹下去了...
这个笑话可以很好的解释 Substitute Algorithm, 对于函数中复杂的算法, 尽量想办法将这个算法简单化, 从而达到与之前同样甚至更好的效果.
本文链接:

熱AI工具

Undresser.AI Undress
人工智慧驅動的應用程序,用於創建逼真的裸體照片

AI Clothes Remover
用於從照片中去除衣服的線上人工智慧工具。

Undress AI Tool
免費脫衣圖片

Clothoff.io
AI脫衣器

Video Face Swap
使用我們完全免費的人工智慧換臉工具,輕鬆在任何影片中換臉!

熱門文章

熱工具

記事本++7.3.1
好用且免費的程式碼編輯器

SublimeText3漢化版
中文版,非常好用

禪工作室 13.0.1
強大的PHP整合開發環境

Dreamweaver CS6
視覺化網頁開發工具

SublimeText3 Mac版
神級程式碼編輯軟體(SublimeText3)

Go語言提供了兩種動態函數創建技術:closures和反射。 closures允許存取閉包作用域內的變量,而反射可使用FuncOf函數建立新函數。這些技術在自訂HTTP路由器、實現高度可自訂的系統和建置可插拔的元件方面非常有用。

在C++函數命名中,考慮參數順序至關重要,可提高可讀性、減少錯誤並促進重構。常見的參數順序約定包括:動作-物件、物件-動作、語意意義和遵循標準函式庫。最佳順序取決於函數目的、參數類型、潛在混淆和語言慣例。

時間複雜度衡量演算法執行時間與輸入規模的關係。降低C++程式時間複雜度的技巧包括:選擇合適的容器(如vector、list)以最佳化資料儲存和管理。利用高效演算法(如快速排序)以減少計算時間。消除多重運算以減少重複計算。利用條件分支以避免不必要的計算。透過使用更快的演算法(如二分搜尋)來優化線性搜尋。

1. SUM函數,用於對一列或一組單元格中的數字進行求和,例如:=SUM(A1:J10)。 2、AVERAGE函數,用於計算一列或一組儲存格中的數字的平均值,例如:=AVERAGE(A1:A10)。 3.COUNT函數,用於計算一列或一組單元格中的數字或文字的數量,例如:=COUNT(A1:A10)4、IF函數,用於根據指定的條件進行邏輯判斷,並返回相應的結果。

C++中的異常處理可透過自訂異常類別增強,提供特定錯誤訊息、上下文資訊以及根據錯誤類型執行自訂操作。定義繼承自std::exception的異常類,提供特定的錯誤訊息。使用throw關鍵字拋出自訂異常。在try-catch區塊中使用dynamic_cast將捕獲到的異常轉換為自訂異常類型。在實戰案例中,open_file函數會拋出FileNotFoundException異常,捕捉並處理該異常可提供更具體的錯誤訊息。

快速的成績查詢工具、這為學生和家長提供了更方便,隨著網路的發展,越來越多的教育機構和學校開始提供線上查成績的服務。讓您輕鬆掌握孩子的學業進展,本文將介紹幾個常用的線上查成績平台。一、便捷-透過網路查詢成績平台可以隨時隨地查詢孩子的考試成績家長可以方便地隨時查詢孩子的考試成績,透過在電腦或手機登入對應的網路查詢成績平台。只要有網路連結、無論是在工作中或在外出時、家長都可以及時了解孩子的學習情況,對孩子進行針對性地輔導和幫助。二、多種功能-除了成績查詢,還提供課表、考試安排等資訊許多網路查成

2024是AI手机的元年,越来越多的手机集成了多项ai功能,通过ai智能技术的赋能,让我们的手机使用更加高效便捷。近日,年初发布的GalaxyS24系列再度提升了其生成式AI的体验,下面下详细的功能介绍,一起来看看吧。一、生成式AI深度赋能三星GalaxyS24系列通过GalaxyAI的赋能,带来了诸多智能化应用,这些功能与SamsungOneUI6.1深度集成,让用户可以随时获得便利的智能体验,显著提升了手机的使用效率和便捷性。由GalaxyS24系列首创的即圈即搜功能是亮点之一,用户只需长按
