Design Patterns - Creational - Abstract Factory Pattern 抽象工廠模式
設計模式 - Abstract Factory Pattern 抽象工廠模式Intro假設我們今天一開始的需求是必須實作出A銀行的金流操作(有刷卡服務跟行動支付),而在往後的需求擴充中,我又必須要新增B銀行的金流操作(一樣具有刷卡服務跟行動支付)
實作簡單工廠一開始我們只會有一個A銀行,所以一開始我們用簡單工廠去解決這個問題
12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152interface ICardPayment{ public function payByCard(): string;}class ABankCardPayment implements ICardPayment{ public function payByCard(): string { return 'ABank 刷卡付款 -> 回饋:' . $this->getCas ...
Design Patterns - Behavioral - Observer Pattern 觀察者模式
設計模式 - Observer Pattern 觀察者模式Intro假設youtube頻道需要很多種通知機制(如:訂閱、鈴鐺、寄信),而在頻道新增影片時我們必須通知我們的使用者。
實作首先,我們先新增YoutubeChannel類別,因為我們希望在新增影片的時候可以通知我們的觀眾,所以我在類別中給訂了一個private變數,希望能夠將我需要通知的對象給儲存進去。
1234567891011121314151617181920212223242526272829303132333435class YoutubeChannel{ private $Notifications = []; public function attach($Notification) { $this->Notifications[] = $Notification; } public function detach($Notification) { foreach ($this->Notificat ...
Design Patterns - Creational - Factory Method Pattern 工廠方法模式
設計模式 - Factory Method Pattern 工廠方法模式Intro假設我們要製作一個計算機,如果使用間單工廠的話,程式碼應該長得如下
12345678910111213141516171819202122232425262728293031323334353637class OperationFactory{ public function createOperator($type): Operation { switch ($type) { case'+': return new Add(); break; case'-': return new Minus(); break; } }}class Add extends Operation{ pu ...
Design Patterns - Creational - Prototype Pattern 原型模式
設計模式 - Prototype Pattern 原型模式Intro假設我們今天要瘋狂產出同一台MacBook裝置,而裝置中皆含有相同規格的配件
實作首先,如果是一般的建立物件方法及使用方法,我們會先寫一個物件,然後再需要用到它的時候將他new出來
12345678910111213141516171819class MacBook{ private $cpu; private $ssd; private $ram; private $monitor; private $keyboard; public function __construct() { $this->cpu = 'i7'; $this->ssd = '256G'; $this->ram = '16G'; $this->monitor = '13 inch'; $this->keyb ...
重構 - Chapter 12 - 處理繼承
重構 - ch12 - 處理繼承提升方法(Pull Up Method)移除重複的程式碼相當重要,如果你有一個函式,而他們重複出現在兩個甚至多個地方,那他很有可能就會變成滋養bug的溫床。你將很有可能在某天改了其中一個,而遺忘了剩下的。
before12345678910111213class father {}class son1 extends father{ public function A();}class son2 extends father{ public function A();}
after12345678910class father { public function A();}class son1 extends father {}class son2 extends father {}
下移方法(Push Down Method)提升方法的逆操作。當你的方法只與某一個子類別有關的時候,或是當需求變更,使得你在不同子類 ...
重構 - Chapter 9 - 組織資料
重構 - ch9 - 組織資料拆開變數(Split Variable)我們經常用變數來保存程式碼產生的結果,以方便引用。如果同一個變數被設定了多次,可能代表變數在方法內的責任超過一個。
1234567891011/**before*/$temp = $length * $width;$temp = $temp * $height;/**after*/$area = $length * $width;$volume = $area * $height;
更改欄位名稱(Rename Field)名稱非常重要,尤其當一個資料結構在很多地方都被使用的時候,好的名稱可以幫助人更快理解程式。
12345678910111213141516/**before*/class Orgnization{ public $name;}/**after*/class Orgnization{ public $title;}
將衍生的變數換成查詢函式(Replace Derived Variable with Query)資料通常都會跟你的程式碼有相當程度 ...
重構 - Chapter 8 - 移動功能
重構 - Ch8 - 移動功能移動函式(Move Function)當你的函式參考其他環境的元素數量,比目前所處的物件來得多時,把他與那些元素放在一起,通常可以改善封裝,讓軟體的其他部分比較不依賴模組的細節
123456789101112131415161718192021222324/**before*/class Account { public function getBankCharge(); //可能根據不同的狀況會有不同的計算方法 public function getOverDraftCharge();}/**after*/class Account { public function getBankCharge(); public function getOverDraftCharge() { return $this->AccountType->getOverDraftCharge() }}//將不同類型的實作細節移動到class A ...
簡潔架構 - Chapter 28 - 測試邊界
Chapter 28 - 測試邊界測試是系統的一部分
測試是系統元件測試程式碼遵循依賴規則,他們非常的詳細且具體,而且他們總是依賴於被測試的程式碼。事實上,你可以將測試視為架構的最外圈,且測試也可以獨立部署。系統中沒有元件依賴於測試,而測試總是依賴於系統元件。
可測試的設計一個未能將測試好好的整合到系統的設計,往往會導致測試的脆弱,而且會使得系統件的僵硬且難以改變。系統元件的改變,即使微不足道,也足以令那些與元件強烈耦合的測試跟著一起改變,導致許多耦合的測試中斷。而如果這種狀況相當劇烈,也就是說,我們對元件做出了一些改變,導致很多的測試因此中斷,這就是所謂的脆弱性測試問題(Fragile Test Problem)。而脆弱的測試則會直接地導致系統的僵化。
簡潔架構 - Chapter 27
Chapter 27 - 服務:偉大與渺小以服務為導向的架構和微服務架構最近變得很流行,流行的原因包括以下幾點:
服務似乎彼此強烈解耦
服務似乎支援開發與部屬的獨立性
以下我們會看到,這種主張都只是『部分正確』
服務是架構?使用服務就本質上而言是一種架構,有些人可能會這樣認為,但事實上顯然不是的。系統的架構是由高層級的策略與低層級細節分離的邊界來定義的,並遵循依賴規則。利用服務來分離功能性通常具有很大的好處,不過服務本身並未定義一個架構。
服務的謬誤這邊我們介紹一些對於服務的一些誤解。
解耦的謬誤把系統拆分為服務的好處就是服務之間會強烈的解耦。畢竟,每個服務都運行在不同的行程中,甚至是不同的處理器上,況且服務之間還不能取用彼此的變數,而且每個服務的介面都有很明確清楚的定義。
這確實是說中了一些事實,但,也不是很多的事實。
單從變數存取層面來說,服務之間確實是解耦的。但如果這些服務彼此之間共享了某些資料,我們將視角拉到資料層面去檢視服務之間的關係,就會發現服務彼此之間還是會因為資料的變動而耦合著。
舉例來說,兩個服務都會用到同一個資料表,而當今天資料表多新增了一個欄位,那麼我勢必就是 ...
簡潔架構 - Chapter 26 - 主元件
Chapter 26 - 主元件Main元件就是最終的細節-也就是最低層次的策略,你可以想像Main是所有元件中最髒的元件。他是系統最初始的進入點,沒有東西依賴他,他的工作是建立工廠(Factory)、實行策略(Strategy)等等。
在Main中,依賴關係應該由依賴注入(Dependency Injection)去實施。
Main將收到的命令需要對應的處理、需要實踐的內容交由較高層級的元件去處理。
12345678910111213141516171819202122232425262728293031323334353637public class Main implements HtwMessageReceiver { private static HuntTheWumpus game; private static int hitPoints = 10; public static void main(String[] args) throws IOException { //Factory game = HtwFactory.makeG ...