[問題] Private method 該不該確認參數正確性?

看板C_and_CPP作者 (火神)時間9年前 (2015/01/25 17:02), 9年前編輯推噓4(4021)
留言25則, 6人參與, 最新討論串1/2 (看更多)
如題 public methods 應該不需要討論了 假設是一個多人合作的專案 你開發的部分很可能之後會換人維護 那麼有必要在 private method 進行參數的 validation 嗎? 我稍微找了一下, 網路上的答案大概有兩類: 1. Using assertion to check in private method 2. Using auto test to insure that the function is not violating your assumptions 大家都認為不該花運算時間在裡面 但人有失蹄馬有亂手 也有可能之後的維護者直接新增 public 介面呼叫 private method 如果是上述的情況似乎 (1), (2) 都無法避免產生問題 不過每個 private method 都檢查參數似乎也有點瘋狂 不知道大家都如何處理此類問題呢? -- ※ 發信站: 批踢踢實業坊(ptt.cc), 來自: 59.120.41.39 ※ 文章網址: https://www.ptt.cc/bbs/C_and_CPP/M.1422176579.A.1A9.html

01/25 17:04, , 1F
目前我是比較傾向或許所有的 function 都該檢查 inputs
01/25 17:04, 1F

01/25 17:20, , 2F
有時pointer可被reference取代,可以減少檢查.
01/25 17:20, 2F
這邊是泛指應該讓程式維持正常的檢查, 就算是 integer 有時也需要檢查~

01/25 18:10, , 3F
我認為不需要,你的例子實作 public member func 的人
01/25 18:10, 3F

01/25 18:10, , 4F
有責任自己 check。
01/25 18:10, 4F

01/25 19:23, , 5F
我我覺得assertion就夠了
01/25 19:23, 5F
我也覺得責任應該在實作 public member func 的人 assertion 就是為了希望在開發期就可以發現

01/25 22:47, , 6F
還是要check啊 總比程式拿到垃圾input不知道還在亂跑好
01/25 22:47, 6F

01/25 22:48, , 7F
多餘的測試交給compiler最佳化處理就好 有問題再抓出來看
01/25 22:48, 7F
Compiler 可以最佳化到這種程度嗎 XD 另外您的有問題是指? 效率有問題 profiling 再去處理嗎?

01/26 20:46, , 8F
是的
01/26 20:46, 8F

01/27 08:39, , 9F
=o= 在C++裡面應該是稱為private class function,BTW
01/27 08:39, 9F
哈哈被其它語言荼毒用習慣 method 了 xD

01/27 08:39, , 10F
回到正題,我不認為private function需要檢查這個
01/27 08:39, 10F

01/27 08:40, , 11F
除非這個parameter是從別的地方拿來的,比方說在functi
01/27 08:40, 11F

01/27 08:40, , 12F
n裡面經由別的service拿到值再塞進自己的private
01/27 08:40, 12F

01/27 08:41, , 13F
我們以前的作法是所謂的邊界防火牆,任何外部值在
01/27 08:41, 13F

01/27 08:41, , 14F
onFetch的時候都要做validation,以這標準來講的話
01/27 08:41, 14F

01/27 08:42, , 15F
public/protected function的parameter跟所有從外部拿
01/27 08:42, 15F

01/27 08:42, , 16F
值得地方(包括private內部)都會先檢查一次
01/27 08:42, 16F

01/27 08:42, , 17F
按這標準的話是不會檢查private function param的
01/27 08:42, 17F
這幾天我仔細了想了一想, 加上諸位先進的想法, 我整理一下目前我的觀點: 1. 為什麼我們要做參數檢查? 為了防止程式產生預期之外的行為 2. 為什麼我們不在 private function 做參數檢查? 因為 private function 的參數是我們能掌握的, 如同殺手貓說的一樣, 有外部防火牆擋住, 所以 pass 給 private function 的參數應該都是正確的 3. 那麼在 private function 做參數檢查有什麼壞處呢? 既然參數是正確的, 多做檢查只是浪費計算資源, 而且會多寫不必要的程式碼 4. Compiler 有可能幫我們最佳化 private function 的參數檢查嗎? 這部分我試寫了一個簡單的小程式: class A { public: float Sqrt(float a) if (a < 0) return 0; else return _Sqrt(a) private: float _Sqrt(a) if (a < 0) return 0; else return sqrt(a) } int main() { A a; cin >> b; cout << a.Sqrt(b); } 在 g++ 4.6.3 -O 沒開的時候的確會檢查兩次, 而 -O 時則只會檢查一次 因此, 也許很多情況, 在 private fucntion 做參數檢查並不會影響太多的效 能 假想一下, 現在有一群人在開發假設, 同一個 class (不一定誰先誰後, 或同時) 我們規定了傳遞給 private function 的人一定要給予正確的參數, 那麼情況會 變成: A 製作了一個 private function _SetupDev, 用在 public function LoadDev B 現在想要使用 _SetupDev: bool _SetupDev(int SleepPeriod, int MaxJobs, int MinJobs); 那麼, B 該傳什麼參數給 _SetupDev? 我想通常的行為要不 B 跑去問 A, 要不 B 必須要去看 LoadDev 寫了什麼 bool LoadDev(string strFileName) { ... if (1 > SleepPeriod || MinJobs < 0 || MaxJobs < MinJobs) { ReportError; } ... 所以 B 了解了 _SetupDev 的 SleepPeriod 不能小於 1... 而另一個方案, 我們規定, 所有 function 都應該檢查它自己的參數正確性, 情況就變成: if (ENUM_OK != _SetupDev(SleepPeriod, MaxJobs, MinJobs)) { ReportError; } or try { ... _SetupDev(SleepPeriod, MaxJobs, MinJobs); } catch ... B 可以完全的不需要知道 _SetupDev 內部詳細的實作, 也可以避免因粗心造 成的參數誤傳; 另一方面, 我想檢查自己的參數正不正確, 感覺比確認給別 人的參數正不正確來得單純 寫到這邊, 我覺得之所以會有這種想法, 也許是因為以我們這種有可能多人 撰寫同一個 class 或維護的情況, 儘管是 private function, 對合作開發 的人來說也可以當作是一層 interface 了吧 但公司的職員往往來來去去, 也許這種狀況也無法避免就是

01/27 18:30, , 18F
function 訊息用 doc 描述,怕開發粗心用 #ifdef DEBUG
01/27 18:30, 18F

01/27 18:31, , 19F
如果開發者自己不注意檢查 input,問題會更多。
01/27 18:31, 19F

01/27 18:33, , 20F
input 指的是任何從外部來的不可控因子。
01/27 18:33, 20F

01/27 18:37, , 21F
如果在 private callee 檢查,caller 卻忘記檢查出現漏
01/27 18:37, 21F

01/27 18:38, , 22F
洞的機會基本上也很大,而且對 caller 來說也是意外的
01/27 18:38, 22F

01/27 18:38, , 23F
錯誤。如果是意料中的例外,又爲何不好好檢查XD?
01/27 18:38, 23F

01/27 18:45, , 24F
不過當然不需要不代表不可以,雖然我覺得這樣不代表更
01/27 18:45, 24F

01/27 18:45, , 25F
defensive 就是了...
01/27 18:45, 25F
的確, caller 忘記檢查也是意外的錯誤, 但或許這個意外錯誤呈現的方式可能會不同? 也許是 Error code v.s. SIGSEGV? XD ※ 編輯: Ebergies (59.120.41.39), 01/27/2015 20:30:27
文章代碼(AID): #1KnB536f (C_and_CPP)
文章代碼(AID): #1KnB536f (C_and_CPP)