→ Ebergies: 目前我是比較傾向或許所有的 function 都該檢查 inputs 01/25 17:04
推 kwpn: 有時pointer可被reference取代,可以減少檢查. 01/25 17:20
這邊是泛指應該讓程式維持正常的檢查, 就算是 integer 有時也需要檢查~
推 carylorrk: 我認為不需要,你的例子實作 public member func 的人 01/25 18:10
→ carylorrk: 有責任自己 check。 01/25 18:10
推 wuliou: 我我覺得assertion就夠了 01/25 19:23
我也覺得責任應該在實作 public member func 的人
assertion 就是為了希望在開發期就可以發現
→ PkmX: 還是要check啊 總比程式拿到垃圾input不知道還在亂跑好 01/25 22:47
→ PkmX: 多餘的測試交給compiler最佳化處理就好 有問題再抓出來看 01/25 22:48
Compiler 可以最佳化到這種程度嗎 XD
另外您的有問題是指? 效率有問題 profiling 再去處理嗎?
→ PkmX: 是的 01/26 20:46
推 Killercat: =o= 在C++裡面應該是稱為private class function,BTW 01/27 08:39
哈哈被其它語言荼毒用習慣 method 了 xD
→ Killercat: 回到正題,我不認為private function需要檢查這個 01/27 08:39
→ Killercat: 除非這個parameter是從別的地方拿來的,比方說在functi 01/27 08:40
→ Killercat: n裡面經由別的service拿到值再塞進自己的private 01/27 08:40
→ Killercat: 我們以前的作法是所謂的邊界防火牆,任何外部值在 01/27 08:41
→ Killercat: onFetch的時候都要做validation,以這標準來講的話 01/27 08:41
→ Killercat: public/protected function的parameter跟所有從外部拿 01/27 08:42
→ Killercat: 值得地方(包括private內部)都會先檢查一次 01/27 08:42
→ Killercat: 按這標準的話是不會檢查private function param的 01/27 08:42
這幾天我仔細了想了一想, 加上諸位先進的想法, 我整理一下目前我的觀點:
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 了吧
但公司的職員往往來來去去, 也許這種狀況也無法避免就是
→ carylorrk: function 訊息用 doc 描述,怕開發粗心用 #ifdef DEBUG 01/27 18:30
→ carylorrk: 如果開發者自己不注意檢查 input,問題會更多。 01/27 18:31
→ carylorrk: input 指的是任何從外部來的不可控因子。 01/27 18:33
→ carylorrk: 如果在 private callee 檢查,caller 卻忘記檢查出現漏 01/27 18:37
→ carylorrk: 洞的機會基本上也很大,而且對 caller 來說也是意外的 01/27 18:38
→ carylorrk: 錯誤。如果是意料中的例外,又爲何不好好檢查XD? 01/27 18:38
→ carylorrk: 不過當然不需要不代表不可以,雖然我覺得這樣不代表更 01/27 18:45
→ carylorrk: defensive 就是了... 01/27 18:45
的確, caller 忘記檢查也是意外的錯誤, 但或許這個意外錯誤呈現的方式可能會不同?
也許是 Error code v.s. SIGSEGV? XD
※ 編輯: Ebergies (59.120.41.39), 01/27/2015 20:30:27