上回設計的「計算運費」範例,用來示範跟練習「使用多型來取代重複的判斷式」,我把它整理在一起,未來可以陸續更新在這篇文章中。
https://tdd.best/code-4-fun/polymorphism-replace-conditions/
還有一些語言沒有題目跟重構步驟,歡迎有興趣的朋友共襄盛舉。
感謝諸位好友的無私貢獻,我已經收到不少 feedback 很感謝大家提供這樣的題目版本,讓他們可以自己參考著練習。
如果大家喜歡這樣的內容,希望您能給 repo 一個 star,給這些無私的朋友一些鼓勵,謝謝你。
如果你覺得搭配 IDE 操作的影片有給你帶來一些幫助(或刺激),也誠摯邀請你訂閱一下 youtube 頻道,按個讚,感謝。
同時也有4部Youtube影片,追蹤數超過4萬的網紅負能量宅肥窮魯蛇 Zackexplosion,也在其Youtube影片中提到,我認為區間測速不該存在的主要原因 而這原因,就是 隱私 前幾天看到邱委員的這篇,我實在不是很認同 - 首先,不得不說邱委員是所有現任立委中最關注交通議題的 但我認為區間測速不單單是交通議題而已 雖然不合理的設置跟跟荒妙的速限都是事實 雖然不合理的設置跟跟荒妙的速限都是事實 雖然不合理的設置跟...
「開放封閉原則」的推薦目錄:
- 關於開放封閉原則 在 91 敏捷開發之路 Facebook 的最佳貼文
- 關於開放封閉原則 在 91 敏捷開發之路 Facebook 的最佳貼文
- 關於開放封閉原則 在 負能量宅肥窮魯蛇 Zackexplosion Youtube 的最佳解答
- 關於開放封閉原則 在 文森說書 Youtube 的精選貼文
- 關於開放封閉原則 在 桃園市議員簡智翔 Youtube 的最讚貼文
- 關於開放封閉原則 在 [心得] Simple Factory in Message-Based C/S Architecture 的評價
- 關於開放封閉原則 在 菜雞與物件導向(11): 開放封閉原則 的評價
- 關於開放封閉原則 在 誠智數位- {設計模式主題研討會之開放封閉原則} OCP ... 的評價
- 關於開放封閉原則 在 Instantly share code, notes, and snippets. - gists · GitHub 的評價
- 關於開放封閉原則 在 Laradiner 讀書會Open Closed Principle 開放封閉原則(1/3) by ... 的評價
開放封閉原則 在 91 敏捷開發之路 Facebook 的最佳貼文
2019 年新課程,【Clean Coder:#DI與AOP進階實戰】,往軟體架構師前進的第一塊敲門磚。
怎麼樣避免成為架構太空人,怎麼樣能捲起袖子針對新系統從無到有,針對 legacy 系統重構成剛好的 clean code,讓你不用再為了擴充的彈性與可測試性煩惱,透過重構讓你不會 over design。
※ 這門課主軸絕對不是在介紹 DI/AOP 框架怎麼樣,而是介紹你能怎樣透過最基本的設計原則、設計模式來解決問題。框架可以幫助你達到哪些便利性。
▍傳送門https://dotblogs.com.tw/hatelove/2018/11/14/201905-dependency-injection-and-aspect-oriented-programming
※ 首梯次課程優惠折抵 3600,錯過不再。
※ 2019 年預計會逐步開一些更進階一點的培訓內容,把整個 clean coder 的 road map 大致底定下來。
▍課程簡介
這門培訓會從物件導向的基本,以解決實務問題與需求為出發點,深入淺出帶著大家了解,為何我們的系統設計需要使用 interface,需要依賴注入。
在沒有依賴注入框架的協助下,你該怎麼用基本原則來解決耦合過高的問題。怎麼應用設計模式來幾解決複雜度過高的設計問題。接著說明,我們可以透過依賴注入框架來幫助我們更方便地處理哪些繁瑣的處理。
帶著大家手把手,把 legacy code 重構成乾淨的設計,如何較無痛地引入依賴注入與 AOP 設計,讓你具備基本的軟體架構設計能力,從此不再為擴充性跟可測試性煩惱。
解決實務設計的問題,例如:
① 你怎麼避免需求異動時,寫出像波動拳一般的 if/else,導致複雜度指數增加,測試案例全都要跟著調整。
② 需求異動時,怎麼樣可以只寫新的類別,靈活地切換實作類別,並組合出新的功能,達到開放封閉原則。
怎麼把安全性的處理(如 Authentication/Authorization)、例外處理、log 與 Cache 等與業務獨立的設計拆分出來,既滿足單一職責,關注點分離,且能在系統上像外掛一般加載設計。
③ 了解如何透過標記式(Attribute/Annotation)設計來優化你的架構設計。
▍課程主題涵蓋範圍
● 耦合過高導致的問題,以及為何會出現複雜度過高
● 依賴反轉原則、介面導向設計、依賴注入設計
● 工廠模式(Factory)、策略模式(Strategy)、裝飾者模式(Decorator)、單例模式(Singleton)
● 依賴注入框架簡介
● 橫切面攔截器設計、獨立測試攔截器
※ 本課程不適合只想嘴砲的人,兩天都是實作,沒有投影片跟講義,只有 dropbox paper + GitHub + flip charts
開放封閉原則 在 負能量宅肥窮魯蛇 Zackexplosion Youtube 的最佳解答
我認為區間測速不該存在的主要原因
而這原因,就是
隱私
前幾天看到邱委員的這篇,我實在不是很認同
-
首先,不得不說邱委員是所有現任立委中最關注交通議題的
但我認為區間測速不單單是交通議題而已
雖然不合理的設置跟跟荒妙的速限都是事實
雖然不合理的設置跟跟荒妙的速限都是事實
雖然不合理的設置跟跟荒妙的速限都是事實
(很重要所以講三次,不然又有一堆奇怪的鄉民眼殘說我在亂噴lol,但本篇沒有要講這部分)
這些也是大家最幹的幹點,但我一直在提倡,也最反對區間測速的點恰恰與委員相反
沒錯,這個有資安疑慮的隱私權問題其實才是最重要的。
我們來看看老早在2018年就生效的歐盟一般資料保護規範法(簡稱GDPR)在維基百科上的部分內容
資料來源:https://reurl.cc/DvoVOQ
-
原則
個人資料的收集應存在適當的限制,進而以合法且公平的方式取得,並且透過適當的方法知會資料來源或者主體,再進一步取得同意。
(不要跟我說區間有掛牌,等看到那牌子最好來得及迴轉離開齁)
保護範圍
個人身份: 電話號碼、地址、車牌等
生物特徵: 歷資料、指紋、臉部辨識、視網膜掃描、相片等
電子紀錄: Cookie、IP 位置、行動裝置 ID、社群網站活動紀錄
(以上幾點內容,就是為什麼最近的網站都會因為Cookie問使用者一堆問題,J點很重要請記得)
法規基礎
被遺忘權 (Right to be forgotten):可以要求控制資料的一方,刪除所有個人資料的任何連結、副本或複製品。
-
以外,我們還要求資料收集方提供我們被收集的資料COPY,這也讓我去年(2020/06) 車子在保養廠整理,結果車牌被拔去開的事情留下了證據,不過這又是另一個故事了,有『需要』的話我再來跟大家分享
圖:https://imgur.com/a/E2v7ZQY
-
接著簡單解釋一下區間測速的原理
區間測速就是用攝影機『監控』所有經過的車輛,利用固定的道路長度,由車輛進入與離開的『時間點』推算出車輛通過的『平均時速』
沒錯,區間測速就是在用路人『未經同意』之下就收集個人資料
他們利用影像辨識,收集了我的車牌,我的行蹤,而且根本不管我有沒有違法!
這也是我最反對的原因!如果我住在坪林,每天不爽給遠通賺錢跑北宜來回,不就等於是每天都告訴政府我幾點回家?幾點上班?
我根本沒有同意這樣的事情啊!
嗯嗯,講到這有些人就會說『啊你不超速就沒事啦』,對啊,不超素就沒事了,但等政府要弄你的時候就出事啦!這樣搞跟強國的人臉辨識,社會信用評價有什麼兩樣?繼續放任這種東西下去就真的兩岸一家親啦
參考:
中國臉部辨識違規闖紅燈系統認錯人,格力電器女總裁中招
https://reurl.cc/e9draR
-
講了那麼多,一定還是有很多人覺得
『啊我又沒做壞事,幹嘛怕這些』
我改變不了這樣的想法,但我想說的是,至少給我們選擇的權利吧!etc雖然做了車牌辨識並記錄,但是在使用者『簽名』同意收集資料前
使用者同意前
使用者同意前
使用者同意前
(這個真的很重要所以要講三次)
ETC連儲值功能都無法開通,甚至連『本人』也無法透過線上系統查詢詳細通行紀錄,只能拿著帳單一筆一筆去超商或其他管道繳費!
比歐盟落後就算了,好歹跟上自家人的etc吧?
雖然etc這樣還是未經同意就收集個人資料(行蹤),但好歹高速公路是完全封閉的系統,我們可以不上高速公路,用海線往返南北,但住在北宜公路上的人們呢?這些人有選擇嗎?
-
所以,請任何一個單位在收集大家的個人資料前,至少先過問,不要弄的大家連選擇的權利都沒了。
喜歡嗎?快來訂♂閱『負能量』的頻道吧!
► https://goo.gl/mJ2Ezn
想出現在遊戲中嘛?趕快來加入頻道會員!
►https://www.youtube.com/channel/UC-r3V6Y2ljXN9kEBq0a5s8A/join
遊戲試玩點這邊(現在只有電腦版)
►https://members.zackexplosion.fun/
抖內肥宅
►https://goo.gl/Qe3ZgR (綠界)
►https://www.paypal.me/zackexplosion ( Paypal )
想要貼紙嗎?點這裡喔
►https://goo.gl/NoEsSL
DISCORD聊天群組
►https://discord.gg/62TBSdj
FB
► https://goo.gl/SmyDfH
IG
►https://www.instagram.com/zackexplosion/
常用BGM
►https://youtu.be/KbUJH8RFCms
爆菊花同意書
► https://goo.gl/cPwBwE
請___簽署這份文件,因為您認為高速/快速公路太危險,而且在不合法的情況下騎上去就沒有素質。
倘若將來,高速公路開放紅黃牌摩托車行駛,與快速道路開放白牌摩托車行駛,本人___同意絕對不在上敘道路上使用摩托車(如:紅黃牌行駛高速公路,白牌行駛快速公路),若違反的話,願意上傳一支自爆菊花影片到社群網站上,表示個人素質與爆菊花決心。
__
近來有許多媒體盜錄影片,拿去當做新聞營利使用。要做新聞報導絕對沒問題,不用聯絡我,但,請寫清楚出處(內文包含影片原始連結或頻道連結),重新上傳之內容不要刻意蓋住片中浮水印即可,請盜錄者自重。
Cameras
► Garmin Virb XE, Samsung Gear 360 ( 2017 )
剪接軟體
► Apple Final Cut Pro X ( Mac 專用 )
#取消禁行機車 #還我高速公路 #不要低能藍藍路 #三讀已過 #認同請分享 #魯蛇 #肥宅 #宅肥 #負能量
開放封閉原則 在 文森說書 Youtube 的精選貼文
前幾個禮拜在Instagram上收到來自一名聽眾的訊息,內容有點真實有點離奇,於是本屬荒誕的我,把它做成一集。
看到《原則:生活與工作》這本書之前,我也從不自覺自己是個封閉的人,直到作者將條條列列的範例攤在面前時,我才深刻覺得自己從沒有認真接受過別人的建言。
若你願意找到最好的答案,而不只是自己想出來最好的答案,這支影片能給你些許建言。
#原則 #文森說書 #文森診療室
若喜歡我的影片或頻道,可以訂閱頻道和分享給朋友,謝謝拉
訂閱頻道: https://www.youtube.com/channel/UCPgGtH2PxZ9xR0ehzQ27FHw?sub_confirmation=1
我會定期每個禮拜上傳一部影片,若你有任何建議或是想聽到我說哪本書,歡迎可以寫信給我,或在Instagram上傳訊息給我也可以。
我的Instagram: https://www.instagram.com/vincent_reading/
我的Bilibili:
https://space.bilibili.com/475005918
開放封閉原則 在 桃園市議員簡智翔 Youtube 的最讚貼文
【智翔的議會質詢-交通局、捷運工程局(10/16)】
#再談公車買一送一政策
桃園公車實施買一送一已有一段時間,我們團隊在檢視去年底的預算過程中,發現市政府在2018年底編列的2019預算中,在「推動公共運輸使用率提升計畫(也就是搭公車買一送一)」這個項目,自行調整刪減了四千萬。
換句話說,預算的編列上應十分充裕,那剩餘的額度是否在今年的預算編列中,擴大更多優惠的適用範圍呢?
例如增加區公所免費市民公車的班次,或是開放非持有市民卡的市民使用買一送一優惠,又或更甚者,讓公車8公里免費呢?
交通局長對這題的回覆相當謹慎,但我想諸如前門下車、後門上車等技術性問題,都是可以經過討論後找出克服的方案,還請交通局慎重考量。
#人行道環境建置
根據內政部在去年的道路養護與人行環境無障礙考評中,桃園市在「人行道設置普及率」、「無障礙設施適宜性比率」兩個項目中獲得了丙等,六都中只有桃園在這兩個項目中「吃餅」;另外,根據內政部與交通部的人行環境規則中,12米以上與25米以上之道路應設人行道與人行庇護島,對於桃園市內重新分配路寬,甚至通盤檢討人行道設置,局長有何想法?
局長則說目前工務局在進行道路整修時會將行人空間考量進去,交通局則會盡力配合。
#中正公園新建地下停車場爭議
#現地公告
從中正公園地下停車場案例中,我們可以發現各局處現在負責的工程中,多少都會面臨民眾抗爭的情形,除了體現出現在的市民對於公民參與以及是否有足夠綠地遊憩越加重視。
對此,我認為往後應訂定跨局處、跨層級的現地公告與民眾參與原則,這樣未來可以減少仰賴傳統的里長系統去做通知,尤其是新的重劃區和社區大樓附近的公共建設,一定要在設計階段做現地公告,蒐集實際使用者的意見。
另外也詢問到,未來的新建工程,能否保持綠覆率不變?地下停車場一案目前工程雖暫緩,但會先調查附近停車場的使用率。目前計畫的執行進度如何?
#捷運綠線
#鐵路地下化
#交通黑暗期
鐵路地下化動工後,林森路與民族路口的地下道將封閉,而捷運綠線在桃園車站動工後,也將開挖站前圓環約一半的面積,若兩者工期重疊,勢必造成長期的交通黑暗期,希望屆時的交維計畫,能在動工前來辦理公開說明會,向市民說明,以利民眾儘早因應。
同樣的捷運綠線動工問題,也請教到捷工局,台鐵站體的文資保存,捷工局應儘早提供施工辦法給予文資科,才能讓綠線車站段及早動工,而綠線的GC02段與GC03段潛盾工作井,到時也應將交維計畫辦理公開說明會,縮短交通黑暗期。
除了地下化路段,高架段也有噪音的問題,台中捷運在試車時發現高架段的軌道有噪音問題,桃園該如何因應?局長則回應,噪音的主因有二,分別是轉彎時以及軌道磨擦發出的噪音,將會針對轉彎路段、高防震路段來做不同的工法,隔音牆的設置也會考量進去。
開放封閉原則 在 菜雞與物件導向(11): 開放封閉原則 的推薦與評價
開放封閉原則 (Open-Close Principle) ... 在我們了解什麼是「對擴展開放」和「對修改封閉」之前,先讓我們談談:什麼是擴展,什麼又是修改呢? 用白話一點的 ... ... <看更多>
開放封閉原則 在 誠智數位- {設計模式主題研討會之開放封閉原則} OCP ... 的推薦與評價
除了解釋OCP的定義之外,另外介紹了其他幾個相關應用。 依賴反轉(Dependency Injection Pattern,DIP) 裝飾者模式(Decorator Pattern) 策略模式( ... ... <看更多>
開放封閉原則 在 [心得] Simple Factory in Message-Based C/S Architecture 的推薦與評價
最近在 porting 一個 Client / Server 架構的網路程式,
Client 利用 Message 的方式跟 Server 溝通。
例如:
client 要向 server 要版本資訊,就傳一個 message struct 給 server
struct msg{
int msg_number;
int size;
void* buf;
};
#define GET_VERSION 100
#define GET_USER_INFO 101
// client
struct msg m;
m.msg_number = 100; // 100 代表 GET_VERSION
...
send(m); // 透過網路傳輸
recv(buffer); // 得到 server 的回傳結果
其中 client / server 溝通的協定是透過 msg_number,
上面 msg_number 100 代表是 GET_VERSION (得到版本資訊)
若是要求 server 傳回使用者資料,則 msg_number 就設成 101
以下是 server 的處理
while(1){
// 取得 msg
...
if(msg == 100){
// 將版本資訊放入 buf 並回傳 (透過網路)
...
}else if(msg == 101){
// 將使用者資訊放入 buf 並回傳
...
}
....
else{
// not implement
}
}
典型的 C style 寫法,很容易理解,
(重點不在網路溝通,我就沒有把網路溝通的 code 寫進去了),
但我發現 msg 大概有一百多種 (101~255),server 的處理會很恐怖
,整個 while (1) 迴圈大概快兩千行 code .... ( ̄□ ̄c|||)a
剛好最近讀了很多 OO 的書,腦袋裝滿了 Design Patterns,
就忍不住來Refactor (重構) 一下 XD
歸納 server code 寫不好的原因如下:
1. 王大娘的裹腳布,又臭又長 (一個函式兩千行,就算 Source Insight也為難)
2. 若要增加新的 msg , 需要動到主程式 ,增加風險
(若不小心 crtl+c , ctrl + v 到別的 msg 就舒服了 ~~)
3. server 主程式跟 msg 間的耦合度太高
(若需資加版本資訊的 log 紀錄,則還是要動到 server 主程式)
以物件導向的術語來說,這也就是違反了 "開放-封閉原則"
(OCP:The Open-Closed Principle),
對修改封閉,對擴充開放。 目前的寫法來說,無論是修改或是擴充都要動到
server 主程式,最好的方式是主程式不動,
若要擴充 msg 則新增一個檔案去實作及可。
我這裡用 C 和 C++ 的方式來講此 server code 作重構
=====================
Refactoring in C's style
=====================
// 將處理 msg 的 code 包成函式
GET_VERSION ==> int ProcessGetVersion(void* buf);
GET_USER_INFO ==> int ProcessGerUserInfo(void* buf);
...
// 宣告函式指標陣列
int (*func_ptr [OP_COUNT+1])(void *buf) = {//OP_COUNT 表示 msg的個數
ProcessGetVersion,
ProcessGetUserInfo,
...
}
// server code
while(1){
// get Msg
...
int ret = (*func_ptr[message_code-100])(m.buf);
}
這樣寫後 server 主程式就很乾淨了,要擴充 msg server code 的部分一行都不用
動,只需要寫一個 process 函式,在註冊到函式指標陣列 fun_ptr 即可。
註: 函式指標的用法可以參考 << The C Programming Language >>
=====================
Refactoring in C++'s style
=====================
物件導向還有一個原則,針對介面寫程式,不要針對實作寫程式,上面 C style
的方法中,每個處理函式都是實作,這樣當 msg 需要做些修改時
(例如為每次的處理加入 log 機制) 都要修改其實作。 觀察一下 server 的行為
(1) get msg (2) process msg 。既然每個 msg 都要做處理,
那就把要做處理的動作抽象起來 (也就是提升為父類別),每個子類別再覆寫其處
理行為。 class 類別階層如下:
// abstract class
class ProcessMsg
{
virtual int process(void* buf) = 0;
virtual ~ProcessMsg();
};
class ProcessGetVersion:public ProcessMsg
{
ProcessGetVersion:public ();
virtual int process(void* buf);
};
class ProcessGetUserInfo: public ProcessMsg
{
ProcessGetUserInfo();
virtual int process(void* buf);
};
接下來再用簡單工廠方法 Simple Factory Method 把產生物件的實作作封裝。
如下:
// server code
while(1){
// get Msg
...
ProcessMsg* obj = simpleFactory(message_code);
int ret = obj->process();
}
ProcessMsg* simpleFactory(int message_code)
{
if( message_code==GET_VERSION){
return new ProcessGetVersion();
}else if(message_code==GET_USERINFO){
return new ProcessGetUserInfo();
...
}else{
}
}
這樣一來就達到"針對介面寫程式,不要針對實作寫程式"的 OO 守則了 (從
server code 的 ProcessMsg* obj = simpleFactory(message_code); 此行觀之)。
這樣寫的語意為, server 主程式得到了一個 ProcessMsg 物件,他不知道實際上
的處理方式 (是要 get_version 還是 get_userInfo),只知道此 ProcessMsg
都需要被 process
因此就直接呼叫 obj->process() , 讓多型機制來決定到底是要 get_version 還
是 get_userInfo。
code 寫到這裡有個很礙眼的地方 = ="
沒錯,就是 simpleFactory() 的內部仍然是用 if else 的方式。若要擴充 msg 仍
然要在 simpleFactory 內部動手腳。
若是可以改成這樣
map<int,string> msg_map;
msg_map[100] = "ProcessGetVersion";
msg_map[101] = "ProcessGetUserInfo";
...
ProcessMsg* simpleFactory(int message_code)
{
return createObject(msg_map[message_code]);
}
那 code 就乾淨又漂亮了,要擴充 msg 只需再繼承 ProcessMsg 類別即可。
注意 createObject 生成的參數是字串,也是就是給予類別的名稱字串,就能夠生
成對應的類別,這種在物件導向的術語叫做動態生成 (Dynamic Creation)
例如:
ProcessMsg* p = createObject("ProcessGetVersion"); // 比照 new ProcessGetVersion();
ProcessMsg* p = createObject("ProcessGetUserInfo");
若是在 Java 的話,有反射機制可以達成 (Reflection)
C++ 語言本身沒有提供 (嘆..) ,不過 MFC 倒是有這個功能。
不過要繼承 CObject 還有加上兩行 Macro : DECLARE_SERIAL 、DECLARE_SERIAL
<< 深入淺出 MFC by 侯捷>> 有詳細的說明。
code 如下: (此 code 在 visual 2008 編譯,此為 console mode,在建立
project MFC 選項要打勾)
==================================
class ProcessMsg
{
protected:
virtual ~ProcessMsg(void){};
public:
virtual int process(void) = 0;
};
class ProcessRequestAllLog : public CObject,public ProcessMsg
// 這裡的多重繼承對於 ProcessMsg 來說只是介面繼承,
// ProcessMsg 語意同 Java 的 Interface
{
DECLARE_SERIAL(ProcessRequestAllLog)
public:
ProcessRequestAllLog(){}
virtual ~ProcessRequestAllLog(){}
virtual int process(void){ cout << "ProcessRequestAllLog" ;}
};
IMPLEMENT_SERIAL(ProcessRequestAllLog ,CObject,0x00)
ProcessMsg* simpleFactory(string str_msg) //
// CRuntimeClass::FromName 的功能好像是 VC7 才開始支援,
// VC6++ 應該是不能編譯 XD
{
ProcessMsg* p = (dynamic_cast<ProcessMsg*>
(CRuntimeClass::FromName(str_msg.c_str())->CreateObject()));
ASSERT(p!=NULL);
return p;
}
int main()
{
ProcessMsg* p = simpleFactory("ProcessRequestAllLog");
//這裡展示動態生成的功能,就沒有加入 message_code 的判斷
p->process();
return 0;
}
==================================
Note: 本以為只要用 DECLARE_DYNCREATE 和 IMPLEMENT_DYNCREATE 這兩個
Macro 即可。但文件上說要用 DECLARE_SERIAL 、DECLARE_SERIAL
https://msdn.microsoft.com/en-us/library/z2z1h62t(VS.80).aspx
這樣的 client / server 架構就比較清爽了~
(希望沒有 overdesign ~ 本來還想要用 Command DP 去做...)
跟大家分享一下~
--
※ 發信站: 批踢踢實業坊(ptt.cc)
◆ From: 61.216.174.15
... <看更多>