[問題] 在流程中插入檢查或不檢查 程式怎麼寫

看板C_and_CPP (C/C++)作者 (殺拉頂)時間6月前 (2023/10/30 00:25), 6月前編輯推噓7(7054)
留言61則, 7人參與, 6月前最新討論串1/2 (看更多)
有遇到一個程式流程中 某些步驟可能要檢查或不檢查的問題 想請問該 怎麼寫比較好. 語言是使用C++ 首先我有一個computing class, 裡面有個member function, 專門負責做計算的動作 而裡面有七個步驟: class Engine::compute(...arguments...) 1. compute1 2. compute2 3. if checking fails this return pre-condition is not satisfied 4. compute3 5. foreach cofig in allowed_user_configurations 6 if checking succeed then store this configuration 7. return allowed_configuration 步驟3)跟步驟6)的檢查是由一個complianceChecker的class來做的: bool compliance.check(....arguments....) 現在呢 為了一些原因 提供了一個選項 可以讓步驟3.)跟步驟6.)的檢查不做-也就是 永遠檢查成功, 請問要怎麼在不動到主流程的狀況下, 來達成這件事情呢? 因為這邊是簡化版本 但其實檢查的地方大概十多處.... 全部都加if-else好像不是太好 如果考慮到未來在其他部分需要加檢查 或是未來 流程異動 這樣if-else很容易漏掉 或是忘記要加if-else 目前我的想法是 加一個wrapper class在compliance checker上 ctor吃一個要不要 做檢查的boolean, 然後有一個perfect forwarding的 member function取代掉 原本的 compliance checker的check function(轉call): class wrapper { public: wrapper(bool doCheckIn): doCheck(doCheckIn) {} template <typename ... Args> bool check(Args&& ... args){ return !doCheck || checker.check(std::forward<Args>(args) ... ); } private: compliance checker bool doCheck; } 然後在第一行之前生成這個wrapper, 用這個wrapper取代掉步驟3.)跟步驟6.)的 compliance class: class Engine::compute(...arguments...) ==> 0. wrapper newChecker(doCheckOrNot); 1. compute1 2. compute2 => 3. if (!newChecker.check(...)) return the pre-condition is not satisfied ...................... 5. foreach cofig in allowed_user_configurations ==> 6. if (newChecker.check(....)) then store this configuration 7. return allowed_configuration 目前這個做法有一些好處: 1. 不動到compliance checker, 而且也不用怕compliance checker的interfance of check function會改變(用template+perfect forwarding處理掉了) 2. 整個流程不變 邏輯上也很分明 就是有檢查跟永遠成功這兩種 但是有些不順的地方: 1.這個wrapper class定位很尷尬, 不知道要當作一個放出來給大家用的class 或是該 跟誰綁在一起 綁在一起是指邏輯關係上.......現在wrapper class九成像syntax sugar 我直接放在CPP file的 anonymous的namespace裡 XDDDDD 未來 若別的地方遇到同一種狀況 是不是又要寫一次? 要不然就要把這個有template的 wrapper class放在header, 但這樣會引進compliance class的dependency..... 2. 要改寫成virtual function的形式嗎? 這樣可繼承之類的 但因為有用到template所以 沒法用virtual function, 而且只有兩種狀況 用virtual是否有效益呢? 3. wrapper class生成後 就決定他的行為了(由ctor的參數決定) 要動態變化就得再多 一組setter/getter. 想要動態變化的理由是 這樣wrapper可當作一個member variable.. 不知道要當作local variable還是member variable比較好...... 其實覺得這種狀況應該是一個非常標準且常見的狀況(二選一) 只是不曉得一般是怎麼 處理的 覺得應該是繼承+virtual function處理居多吧? 但個人比較傾向少用繼承 先嘗試template + 組合的方式, 或是virtual function是做在別的地方的方式 P.S. compliance checker是我們動不了的一個class....... 在此 想請各位給一些想法跟建議~~~謝謝~~~ -- ※ 發信站: 批踢踢實業坊(ptt.cc), 來自: 1.164.105.187 (臺灣) ※ 文章網址: https://www.ptt.cc/bbs/C_and_CPP/M.1698596742.A.6F2.html ※ 編輯: saladim (1.164.105.187 臺灣), 10/30/2023 00:26:06 ※ 編輯: saladim (1.164.105.187 臺灣), 10/30/2023 00:29:29

10/30 08:41, 6月前 , 1F
你這個這麼 procedure 的東西,如果是 business logic 就
10/30 08:41, 1F

10/30 08:41, 6月前 , 2F
照著 business logic 的架構寫,例如如果 business logic
10/30 08:41, 2F

10/30 08:41, 6月前 , 3F
在這邊就是每次都先確認是否做檢查,那你就照著它架構寫
10/30 08:41, 3F

10/30 08:41, 6月前 , 4F
,每個檢查外面都包上 if else,不要做一些自以為聰明的"
10/30 08:41, 4F

10/30 08:41, 6月前 , 5F
設計"
10/30 08:41, 5F

10/30 08:41, 6月前 , 6F
如果 business logic 在這邊有做抽象,例如要檢查和不檢
10/30 08:41, 6F

10/30 08:41, 6月前 , 7F
查被分成兩種不同的流程,在不同情況下使用,兩種流程有
10/30 08:41, 7F

10/30 08:41, 6月前 , 8F
各自的名字,那就把兩種流程分成兩個函式,不要自以為寫
10/30 08:41, 8F

10/30 08:41, 6月前 , 9F
成一個函式 reusing 很聰明
10/30 08:41, 9F

10/30 08:41, 6月前 , 10F
如果這不是 business logic 而是你為了達成 business log
10/30 08:41, 10F

10/30 08:41, 6月前 , 11F
ic 而寫出來的演算法,那我只能說真的慘
10/30 08:41, 11F

10/31 03:17, 6月前 , 12F
意思是說直接if-else嗎? 比起繼承我還比較可以接受 繼承
10/31 03:17, 12F

10/31 03:19, 6月前 , 13F
太難model了 對了 這邊是簡化過的程式 實際上複雜許多 很
10/31 03:19, 13F

10/31 03:20, 6月前 , 14F
多地方要考慮加 基本上是一個template+strategy pattern
10/31 03:20, 14F

10/31 03:21, 6月前 , 15F
的組合 設定/caller無關的都拿掉了 不是單單一堆function
10/31 03:21, 15F

10/31 03:22, 6月前 , 16F
call..另外我的一個疑問就是 通常有個二選一的選項 但是
10/31 03:22, 16F

10/31 03:24, 6月前 , 17F
要嘛做個抽象有點多餘(因為永遠不會有更多選項) 要嘛 無
10/31 03:24, 17F

10/31 03:25, 6月前 , 18F
法用現有體系去model這個抽象 或是它本身就是一個獨立的
10/31 03:25, 18F

10/31 03:27, 6月前 , 19F
不知道一般是怎麼處理 這個case, 因為流程固定了所以兩個
10/31 03:27, 19F

10/31 03:28, 6月前 , 20F
是不行的......以上....大概補充說明一下.....
10/31 03:28, 20F

10/31 11:07, 6月前 , 21F
你比較可以接受繼承的具體原因我沒看到?
10/31 11:07, 21F

10/31 11:07, 6月前 , 22F
如果你對 if else 的 concern 只是像你內文說的"怕以後
10/31 11:07, 22F

10/31 11:07, 6月前 , 23F
忘記加",那你可能要再想想,我不太能理解忘記做該做的工
10/31 11:07, 23F

10/31 11:07, 6月前 , 24F
作是個什麼概念
10/31 11:07, 24F

10/31 11:07, 6月前 , 25F
1. 你用 if else 不會影響未來制定 business logic 的人
10/31 11:07, 25F

10/31 11:07, 6月前 , 26F
考慮到檢查/不檢查兩種情況
10/31 11:07, 26F

10/31 11:07, 6月前 , 27F
2. 也不會影響未來寫 jira ticket 的時候的 description
10/31 11:07, 27F

10/31 11:07, 6月前 , 28F
和 acceptance criteria 忘記這兩種情況
10/31 11:07, 28F

10/31 11:07, 6月前 , 29F
3. 也不會影響原本該做的 code review 變成沒做
10/31 11:07, 29F

10/31 11:07, 6月前 , 30F
4. 也不會影響 unit tests 忘記測
10/31 11:07, 30F

10/31 11:07, 6月前 , 31F
5. 也不會影響 testers 的 test plan 忘記加這個測項
10/31 11:07, 31F

10/31 11:07, 6月前 , 32F
完全看不出來怎麼會影響任何一個人忘記考慮檢查/不檢查
10/31 11:07, 32F

10/31 11:07, 6月前 , 33F
兩種情況
10/31 11:07, 33F

10/31 11:07, 6月前 , 34F
看你的內文和回覆感覺最大的問題是你在用寫通用函式庫的
10/31 11:07, 34F

10/31 11:07, 6月前 , 35F
思維寫 user code,這樣寫出來的東西不覺得就像是用營造
10/31 11:07, 35F

10/31 11:07, 6月前 , 36F
業 sop 蓋的疊疊樂一樣嗎
10/31 11:07, 36F

10/31 12:32, 6月前 , 37F
不懂你說的忘記加是什麼情況,多了cpmpute忘記補檢查?
10/31 12:32, 37F

10/31 12:33, 6月前 , 38F
general就是所有compute都有check,只是chk可以noop
10/31 12:33, 38F

10/31 12:35, 6月前 , 39F
或所有compute跟check都當做callback執行,繼承沒有必要
10/31 12:35, 39F

10/31 12:36, 6月前 , 40F
如果對效能有需求,那看情況決定要不要generalize
10/31 12:36, 40F

10/31 12:38, 6月前 , 41F
重點是你的抽象化可以用在別的地方嗎?好debug嗎?
10/31 12:38, 41F

11/01 09:06, 6月前 , 42F
改用rust的operator?
11/01 09:06, 42F

11/02 03:14, 6月前 , 43F
繼承對我的順位會在第二或更之後 怕忘了加是有了這logic
11/02 03:14, 43F

11/02 03:15, 6月前 , 44F
在 若是要改or加新的處理(不是其他bussiness logic變動)
11/02 03:15, 44F

11/02 03:16, 6月前 , 45F
在做check的時候 可能會忘記有這條 實際的東西還蠻多的若
11/02 03:16, 45F

11/02 03:18, 6月前 , 46F
不是用同一個util(不管是func or class) 會有機會漏掉
11/02 03:18, 46F

11/02 03:21, 6月前 , 47F
當然1~5也有道理 其他大大建議我也會一併想一想 其實不到
11/02 03:21, 47F

11/02 03:22, 6月前 , 48F
寫通用函式庫 當會很多東西常出現 但組合他們的邏輯變動
11/02 03:22, 48F

11/02 03:23, 6月前 , 49F
很快(bussiness logic/requests...) 一定會有一個自己的"
11/02 03:23, 49F

11/02 03:25, 6月前 , 50F
好用函式庫/engine庫" XD 才能改得快 重複使用"解"
11/02 03:25, 50F

11/04 10:30, 6月前 , 51F
最個macro取代不就好了?搞這麼複雜?
11/04 10:30, 51F

11/04 12:29, 6月前 , 52F
我會認為這個「選項」應該要是 business logic 的一部份
11/04 12:29, 52F

11/04 12:30, 6月前 , 53F
是的話其實也沒什麼「忘了」的問題, 因為那就是沒實作完全
11/04 12:30, 53F

11/04 12:31, 6月前 , 54F
如果未來要加其他開關的話應該要以等同改變 business logic
11/04 12:31, 54F

11/04 12:31, 6月前 , 55F
的型式去處理, 而不只是加一個開關調整這種事
11/04 12:31, 55F

11/04 12:36, 6月前 , 56F
講更簡單一點就是, 加開關應該要以等同於改流程的程度對待
11/04 12:36, 56F

11/04 12:36, 6月前 , 57F
(實際上真的在改流程, 新增某條件之下某流程可跳過的邏輯)
11/04 12:36, 57F

11/04 12:37, 6月前 , 58F
未來不管是加別的開關或是流程調整都要順過整個流程才實作
11/04 12:37, 58F

11/04 12:38, 6月前 , 59F
這樣這些開關是流程的一部份, 就不會有什麼「忘記」的問題
11/04 12:38, 59F

11/06 03:30, 6月前 , 60F
DP, chain of responsibility 參考看看,對於流程控管非
11/06 03:30, 60F

11/06 03:30, 6月前 , 61F
常好用
11/06 03:30, 61F
文章代碼(AID): #1bFeU6Ro (C_and_CPP)
文章代碼(AID): #1bFeU6Ro (C_and_CPP)