基本介紹
- 中文名:程式設計三次法則
- 外文名:Three rules of programming
- 概述:代碼重構的一條經驗法則
- 學科:計算機科學
簡介,原理,C++編程中的三次法則,C/C++ 原始碼三次法則示例,頭檔案header.h,主函式main.cpp,頭檔案實現 header.cpp,
簡介
三次法則的要求是:
允許按需直接複製貼上代碼一次,但如果相同的代碼片段重複出現三次以上的時候,將其提取出來做成一個子程式就勢在必行。
馬丁·福勒在《重構》一書中介紹了三次法則,並認為這一法則是Don Roberts所提出。
原理
在編程中,由於會提高代碼維護的難度,直接複製代碼段的習慣並不好;具體來說,當有代碼片段需要變更時,代碼維護者就必須找出程式中所有與之相同的代碼片段,並都進行修改,但這一過程易出差錯,而且也常會帶來許多麻煩。相對的,如果代碼只在一個地方出現,修改起來就容易多了。
這一法則在代碼量(即行數)較少(甚至只有一行)的時候還有另一種形式的套用,例如:如果你想調用一個函式,並在調用失敗的時候再嘗試調用一次,那使用兩處調用亦可;但若你想在放棄嘗試前至少嘗試5次(注意,這裡的5匹配>=3的要求),那就應該將其寫成循環形式,使代碼中只有一個調用位置。
C++編程中的三次法則
- 賦值運算符 (C++)
上述三個函式是特別的成員函式,假如程式設計師沒有自行定義或宣告這三個函式,編譯器會自動地創建他們並且編譯到應用程式內。然而,如果程式設計師僅定義其中一個,其餘兩個函式仍然會由編譯器自動產生,這種混雜的情況非常容易產生程式設計師難以預期的錯誤。三法則的存在,正是提醒程式設計師避免那樣的陷阱。
C/C++ 原始碼三次法則示例
頭檔案header.h
#ifndef _HEADER_H_#define _HEADER_H_//// 判斷是否為微軟編譯器#ifndef _MSC_VER#undef NULL#define NULL 0#endif//#include <iostream>#include <limits>//using std::cin;using std::cout;using std::endl;//// 類別:方塊class CCube{public: // 建構子 CCube(); // 含有參數的建構子 CCube(double length, double width, double height); // 三法則:解構子 ~CCube(); // 三法則:複製建構子 CCube(const CCube &sample); // 三法則:設定運運算元 CCube& operator=(const CCube &sample); // 設定長寬高 void setLength(double length); void setWidth(double width); void setHeight(double height); // 取得長寬高 double getLength() const; double getWidth() const; double getHeight() const; // 計算體積 double getVolume() const;protected:private: // 長寬高 double m_Length; double m_Width; double m_Height;};//void PAUSE(void);//#endif
主函式main.cpp
#include"header.h"//// 判斷是否為微軟編譯器#ifndef _MSC_VERint#elsevoid#endifmain(int argc, char* argv[]){ // 方塊零 CCube cube0(4.3, 5.2, 6.1); // 第一個方塊 { cout << "=== No.1 cube ===" << endl; CCube cube1 = cube0; cout << "Volume of cube = " << cube1.getVolume() << endl; } // 第二個方塊 { cout << "=== No.2 cube ===" << endl; CCube cube2; cube2 = cube0; cout << "Volume of cube = " << cube2.getVolume() << endl; } PAUSE(); return#ifndef _MSC_VER EXIT_SUCCESS#endif ;}
頭檔案實現 header.cpp
#include "header.h"//void PAUSE(void){ cin.clear(); cin.ignore(std::numeric_limits<std::streamsize>::max(), '\n'); cout << "press any key to continue..."; cin.get();}CCube::CCube(){ cout << "Constructor: CCube()" << endl; this->m_Length = 0.0; this->m_Width = 0.0; this->m_Height = 0.0;}CCube::CCube(double length, double width, double height){ cout << "Constructor: CCube(length, width, height)" << endl; this->m_Length = length; this->m_Width = width; this->m_Height = height;}CCube::~CCube(){ cout << "Destructor: ~CCube()" << endl; this->m_Length = 0.0; this->m_Width = 0.0; this->m_Height = 0.0;}CCube::CCube(const CCube &sample){ cout << "Copy constructor: CCube(const CCube &sample)" << endl; // // 保護:禁止設值給自己 if (this != &sample) { this->m_Length = sample.m_Length; this->m_Width = sample.m_Width; this->m_Height = sample.m_Height; }}CCube& CCube::operator=(const CCube &sample){ cout << "Assignment operator: operator=(const CCube &sample)" << endl; // // 保護:禁止設值給自己 if (this != &sample) { this->m_Length = sample.m_Length; this->m_Width = sample.m_Width; this->m_Height = sample.m_Height; } return *this;}double CCube::getVolume() const{ return (this->m_Length * this->m_Width * this->m_Height);}