市面上很多文章、影片分享了物件導向要如何應用。
卻很少人分享這些概念是為了解決什麼問題,所以很多人就算學完了物件導向的概念,卻依舊沒有把它應用在手上的專案。
因此這個系列文中,筆者會先分享「直線思考下」我們會設計出怎樣糟糕的程式;接著再來討論如何應用物件導向的概念對程式做 Refactoring,提升程式未來的擴充性、維護性。
大綱一、設計考卷二、如果考卷的 Class 也被其他工程師使用三、我們希望在「設定答案」時通知其他老師四、老闆…我改不動了,打算用封裝進行重構五、所以「封裝(Encapsulation)」這個概念幫我們解決了什麼問題?
一、設計考卷
假使我們今天要製作一個線上考試的系統,相信「考卷」是考試的必要元素之一,今天我們就用它來舉例,說明「封裝」的重要性。
這邊我們先簡單定義「考卷(ExaminationPaper)」該有的屬性,像是「試卷名稱(name)、題目(questions)、答案(answers)」。
如果我們想要使用裡面的屬性,只要透過 new 將它實體化,接著用「.」就能夠存取使用,像是下面的範例中我們新增了一份「數學」考卷。
二、如果考卷的 Class 也被其他工程師使用
上面直接給考卷「試卷名稱、題目、解答」的方式看起來是不是很清爽?
但如果今天這個系統除了你之外,還有其他的工程師也使用了這個考卷的 Class,在其他檔案去新增諸如「英文、國文、歷史…」的考卷,你覺得未來可能會發生什麼問題呢?
三、我們希望在「設定答案」時通知其他老師
今天設想一個情境,老師可能在出完考卷後發現提供的答案寫錯了,因此需要修改試卷答案;而校方為了確保試卷答案的正確性,希望系統可以在「設定答案」時發信通知其他老師,讓大家確認答案是否正確。
好的,此時身為工程師的你會怎麼做?
去搜尋所有「examinationPaper.answers」的程式,然後在後面加上「sendEmail」的函式嗎?
如果你真的採用上面的做法,假使這個試卷的 Class 被引用 100 次,那就需要在那 100 個地方新增「sendEmail」的函式;這個做法不但會增加日後程式維護的困難度,要是不久後校方要求「設定答案時,需要先經過審核」,那你就會改到想死吧?
系統在設計時,就需要考慮到未來的擴充性;否則在需求變更時會死得很慘。
四、老闆…我改不動了,打算用封裝進行重構
過去我們把「name、questions、answers」都設定為 public 可以直接存取,但就如同上面的範例,正因為可以「直接存取」而導致未來程式擴充性的問題。
因此在重構上,我們將「name、questions、answers」改為 private,如果想要存取則要透過 Getters、Setters 的函式。
重構後,儘管我們 ExaminationPaper 的 Class 變得更長,但是日後有其他需求新增時,我們可以更靈活的變更,維護性、可讀性、擴充性都增加不少。
以今天重構後的 Class 舉例,如果日後使用到設定答案:
examinationPaper.answers = [...];
就會觸發到 sendEmail
的函式。
五、所以「封裝(Encapsulation)」這個概念幫我們解決了什麼問題?
- 透過封裝,我們可以保護 Class 屬性,不讓人隨意修改。
- 資料讀取、變更,透過 Getters、Setters 統一處理。
- 因為把方法封裝,所以在需求變更時,只要修改一個地方,不需要在每個用到的地方都修改。
▶︎ 用 TypeScript 學物件導向▋ 封裝(Encapsulation)能解決什麼問題?(本篇)
▋ 多型(Polymorphism)&繼承(Inheritance)能解決什麼問題?▶︎ 如果這篇文章有幫助到你1. 可以點擊下方「Follow」來追蹤我~
2. 可以對文章拍手讓我知道 👏🏻你們的追蹤與鼓勵是我繼續寫作的動力 🙏🏼▶︎ 如果你對工程師的職涯感到迷茫1. 也許我在iT邦幫忙發表的系列文可以給你不一樣的觀點 💡
2. 也歡迎您到書局選購支持,透過豐富的案例來重新檢視自己的職涯