찾다
php教程php手册详细介绍优化函数的构成

详细介绍优化函数的构成

Jun 13, 2016 am 11:13 AM
extractmethod아래에소개하다최적화여러 종류기능발견하다구성하다~의설명하다상세한

下面介绍了几种优化函数

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, 对于函数中复杂的算法, 尽量想办法将这个算法简单化, 从而达到与之前同样甚至更好的效果.

本文链接:

성명
본 글의 내용은 네티즌들의 자발적인 기여로 작성되었으며, 저작권은 원저작자에게 있습니다. 본 사이트는 이에 상응하는 법적 책임을 지지 않습니다. 표절이나 침해가 의심되는 콘텐츠를 발견한 경우 admin@php.cn으로 문의하세요.

핫 AI 도구

Undresser.AI Undress

Undresser.AI Undress

사실적인 누드 사진을 만들기 위한 AI 기반 앱

AI Clothes Remover

AI Clothes Remover

사진에서 옷을 제거하는 온라인 AI 도구입니다.

Undress AI Tool

Undress AI Tool

무료로 이미지를 벗다

Clothoff.io

Clothoff.io

AI 옷 제거제

AI Hentai Generator

AI Hentai Generator

AI Hentai를 무료로 생성하십시오.

인기 기사

R.E.P.O. 에너지 결정과 그들이하는 일 (노란색 크리스탈)
3 몇 주 전By尊渡假赌尊渡假赌尊渡假赌
R.E.P.O. 최고의 그래픽 설정
3 몇 주 전By尊渡假赌尊渡假赌尊渡假赌
R.E.P.O. 아무도들을 수없는 경우 오디오를 수정하는 방법
3 몇 주 전By尊渡假赌尊渡假赌尊渡假赌
WWE 2K25 : Myrise에서 모든 것을 잠금 해제하는 방법
4 몇 주 전By尊渡假赌尊渡假赌尊渡假赌

뜨거운 도구

MinGW - Windows용 미니멀리스트 GNU

MinGW - Windows용 미니멀리스트 GNU

이 프로젝트는 osdn.net/projects/mingw로 마이그레이션되는 중입니다. 계속해서 그곳에서 우리를 팔로우할 수 있습니다. MinGW: GCC(GNU Compiler Collection)의 기본 Windows 포트로, 기본 Windows 애플리케이션을 구축하기 위한 무료 배포 가능 가져오기 라이브러리 및 헤더 파일로 C99 기능을 지원하는 MSVC 런타임에 대한 확장이 포함되어 있습니다. 모든 MinGW 소프트웨어는 64비트 Windows 플랫폼에서 실행될 수 있습니다.

SublimeText3 Linux 새 버전

SublimeText3 Linux 새 버전

SublimeText3 Linux 최신 버전

DVWA

DVWA

DVWA(Damn Vulnerable Web App)는 매우 취약한 PHP/MySQL 웹 애플리케이션입니다. 주요 목표는 보안 전문가가 법적 환경에서 자신의 기술과 도구를 테스트하고, 웹 개발자가 웹 응용 프로그램 보안 프로세스를 더 잘 이해할 수 있도록 돕고, 교사/학생이 교실 환경 웹 응용 프로그램에서 가르치고 배울 수 있도록 돕는 것입니다. 보안. DVWA의 목표는 다양한 난이도의 간단하고 간단한 인터페이스를 통해 가장 일반적인 웹 취약점 중 일부를 연습하는 것입니다. 이 소프트웨어는

Atom Editor Mac 버전 다운로드

Atom Editor Mac 버전 다운로드

가장 인기 있는 오픈 소스 편집기

안전한 시험 브라우저

안전한 시험 브라우저

안전한 시험 브라우저는 온라인 시험을 안전하게 치르기 위한 보안 브라우저 환경입니다. 이 소프트웨어는 모든 컴퓨터를 안전한 워크스테이션으로 바꿔줍니다. 이는 모든 유틸리티에 대한 액세스를 제어하고 학생들이 승인되지 않은 리소스를 사용하는 것을 방지합니다.