[中文版在此:](https://vocus.cc/article/67bafcecfd897800011d89b1) {%preview https://vocus.cc/article/67bafcecfd897800011d89b1 %} ## System design ### SOLID rules for OOP | Principle | Description | simple words | e.g. | | --- | --- | --- | --- | | **S**ingle responsibility principle | A module should be responsible to one, and only one, actor. | _i.e. <span style='color: #fa8072;'>one module one function</span>_ | `login` module shall not has transaction function | | **O**pen-closed principle | software entities (classes, modules, functions, etc.) should be `open for extension`, but `closed for modification` | _i.e. <span style='color: #fa8072;'>open for extension, closed for modification</span>_ | If we wanna add a function for Paypal, create a new check function instead of modifying the current one | | **L**iskov substitution principle | replacing a superclass object with a subclass one shall not affect the system's correctness | _i.e <span style='color: #fa8072'>offspring shall bear all traits its parents have</span>_ <br> ![car example for Liskov substitution principle](https://resize-image.vocus.cc/resize?compression=6&norotation=true&url=https%3A%2F%2Fimages.vocus.cc%2F239230cf-4eb2-4cfe-95f8-ec29114ac41d.png&width=740&sign=GdQ25f6dCpK7UfMyiNcaaG9NgpxpeSmo0vMdWgMkLb8) | a lorry bears all features a car shall have, but a car doesn't | | **I**nterface segregation principle | A client should never be forced to implement an interface that it doesn't use | _i.e. <span style='color: #fa8072;'>throw out irrelevant or unnecessary functions from the interface</span>_ | There is an printer interface with `print` and `scan` methods. If Woof only has `scan` demand, we shall not force him to implement the interface containing `print` | | **D**ependency inversion principle | High-level modules should not import anything from low-level modules. Both should depend on abstractions (e.g., interfaces).<br> Abstractions should not depend on details. Details (concrete implementations) should depend on abstractions. | _i.e. <span style='color: #fa8072;'>change anything in lower-module shouldn't affect the higher ones</span>_ | Someday Ibi finds his PS5 controller broken, he just needs to buy a new controller rather than the whole PS5 set since PS5 doesn't rely on its controller | --- ## Common design pattern | Design pattern | simple description | analogy in real life | | --- | --- | --- | | Prototype | creating by cloning | write CV from template | | Singleton | One class one global-accessible instance | government | | factory | order -> objects, without knowing the manufacturing process | order an iphone _Rarely do people know how their iPhone is made_ | | Abstract Factory | factory's blueprint | the blueprint of Giant's factories | | Builder | Separation of production processes | Ford car's manufacture | | Dependency Injection | functions outsourcing | putting a battery in the phone instead of co-production | ### Prototype Pattern ![prototype pattern illustration](https://resize-image.vocus.cc/resize?compression=6&norotation=true&url=https%3A%2F%2Fimages.vocus.cc%2Fd8f0c7c7-6ada-497b-b4f7-6e52613a333c.png&width=740&sign=LVsXC_saPRmmH6HNNgZJ--4JpwJ4q2H5YBzNznV28bQ) <span style='font-size: 0.64em;'>source: Ibi, i.e. me</span> * Definition: creating objects by cloning rather than instantiating a whole new one _Just like using template_ * Why? * Efficiency * Management If you want to make some adjustion, you only need to modify the template * Example: * `Ctrl` + `C` -> `Ctrl` + `V` * Using a template to write Curriculum Vitae instead of scratching from a blank sheet ### Singleton <!-- https://refactoring.guru/design-patterns/singleton --> ![Singleton illustration](https://resize-image.vocus.cc/resize?compression=6&norotation=true&url=https%3A%2F%2Fimages.vocus.cc%2Fdd5f370b-1c9c-44ee-a63f-4a5f6f2113b9.png&width=740&sign=VAlFS20_pGlZaBQAQzl7x2oRI6eDPEBfVzrvJFFa7jc) <span style='font-size: 0.64em;'>source: Ibi, i.e. me</span> * definition: * One class one instance * global access point * Why? * Resource sharing * Instantiation efficiency some objects may require higher cost for instantiation * Management convenience one access point for all objects * Examples: * DB connection pool * Log system * config file manager * Government * cons: * Violating **Single responsibility principle** * High coupling level -> difficulty for unit test -> modification may affect other functions * global variable corruption * multi-thread safety - - -> Double-Checked Locking Pattern (lock hint) ### Factory Pattern * Definition: Separation of production and utilisation _users don't need to know the producing process, just giving order_ * How? * Object creation: The main goal is to create objects * Abstraction: You don't need to know the specific details in production process * Separation of Concern: User knows nothing about how their object created, leading to cleaner code and higher maintainability * Why? * Flexibility: New types of objects are able to be made without downstream code modification * Maintainability * Code Clarity * Real-life example: * Pizza making: Recall the last time you ordered a pizza. You just needed to say what you like to eat, rather than **how the pizza shall be made**, right? * Car factory: When purchasing a car, buyers only have to tell seller what they want. **How** the car pops up isn't important ### Abstract Factory Pattern * Definition: The blueprint for factories, i.e. factories' factory * Purpose: Creating families of related objects without specifying their concrete classes * Relationship: * Abstract factory * factories * objects * Example: * GUI design blueprint: abstract factory * GUI for Windows: factory * some buttons: objects * GUI for Mac: factory * some buttons: objects ### Builder Pattern ![builder pattern illustration](https://resize-image.vocus.cc/resize?compression=6&norotation=true&url=https%3A%2F%2Fimages.vocus.cc%2F240c9346-34b2-437b-8ea5-d79af911f8f8.png&width=740&sign=UVaPVEUScU_ps4U2JOOoqupfoEJm-VJHqqwQ4ZWKpk8) <span style='font-size: 0.64em;'>source: Ibi, i.e. me</span> * Definition: Separation of production processes * Why? * Make a complex thing all at once may be difficult, while do it stepwise can be much easier * Avoiding **telescoping constructors** _Several constructors in the same class just for different parameter number acceptance, thus an anti-pattern_ * How? * One step one builder, and they only need to do their own job * Real-life example: * When building a computer, its components such as CPU, GPU, RAM, etc. are made in different places before assembly ### Dependency Injection (DI) Pattern ![dependency injection pattern illustration](https://resize-image.vocus.cc/resize?compression=6&norotation=true&url=https%3A%2F%2Fimages.vocus.cc%2F189d115d-4074-4263-ac03-f609e5b6f224.png&width=740&sign=i5cWfPgtpCFNrqoj7Su0Wx0KEADyT6gAnTTYRK_8S_4) <span style='font-size: 0.64em;'>source: Ibi, i.e. me</span> * Principle: Module/class gets its required functions from outside, rather than creating them itself * Terminology * Dependency: the requirement for something to perform some functions e.g. A car _depends_ an engine to run => engine is the car's dependency * Injection: giving something from outside into an entity e.g. Placing a battery into a phone instead of making it a part of a phone ~~like modern smart phone~~ * Why? * loose coupling * Flexibility * Higher testability * Cleaner code --- ## Design patterns for service ### 3-tier architecture ![three-tier architecture figure: ](https://www.researchgate.net/profile/Muhammad-Ehsan-Rana/publication/357819645/figure/fig1/AS:1120708604231682@1644209161532/Tier-Architecture-Pattern.jpg) <span style='font-size: 0.64em;'>source: Muaz, Abdulla & Rana, Muhammad Ehsan & Hameed, Vazeerudeen. (2021). A Framework for Catering Software Complexity Issues Using Architectural Patterns. 554-561. 10.1109/IEEECONF53624.2021.9668115.</span> * presentation tier (client end) * business logic tier (server) * Data access tier (database) * why use 3-tier architecture? * Separation of Concerns -> maintainability * Scalability * Security * Reusability * Decoupling ### MVC **M**odel-**V**iew-**C**ontroller * Model: business-logic-handling programme * View: GUI module * Controller: task-assigning programme ### MVP **M**odel-**V**iew-**P**resenter * Model: business-logic-handling programme * View: GUI module * Presenter: handling the data and sending it to View ### MVVM **M**odel-**V**iew-**V**iew**M**odel * Model: business-logic-handling programme * View: GUI module * ViewModel: process the data into view-format * Binder connects the Data and View * Data change in ViewModel will affect view _ViewModel can be unit-tested independently, real-UI is unnecessary during the unit test_ ### Summary | Sub-structure | Presentation tier | Logic tier | Data tier | | :---: | :---: | :---: | :---: | | MVC | View (GUI) | Model and Controller | Database | | MVP | View | Model and Presenter | Database | | MVVM | View | ViewModel and Model | Database | <!-- ## 常見設計模式 | 設計模式 | 這什麼? | 生活類比 | | --- | --- | --- | | 原型 (Prototype) | 複製 \+ 修改 \= 創建 | 用模板寫履歷 | | 單例 (Singleton) | 一個類別,一個全域可存取的實例 | 政府機關 | | 工廠 (Factory) | 下訂單 -> 物件,無需了解製造過程 | 訂購 iPhone _很少買家知道 iPhone 生產細節_ | | 抽象工廠 (Abstract Factory) | 工廠的藍圖 | 捷安特工廠藍圖 | | 製造者 (Builder) | 生產流程的分離 | 福特式生產 (流水線工人各自負責拆解後的工作) | | 相依性注入 (Dependency Injection) | 函數外包 | 給手機裝電池,而非把電池做在手機上 | --> <!-- | 子結構 | 展示層 (Presentation tier) | 商業邏輯層 (Logic tier) | 資料層 (Data tier) | | :---: | :---: | --- | :---: | | MVC (模型-視圖-控制器) | 視圖 (GUI View) | 模型 (Model) 與 控制器 (Controller) | 資料庫 (Database) | | MVP (模型-視圖-展示器) | 視圖 (View) | 模型 (Model) 與 呈現者 (Presenter) | 資料庫 (Database) | | MVVM (模型-視圖-視圖模型) | 視圖 (View) | 視圖模型 (ViewModel) 與 模型 (Model) | 資料庫 (Database) | -->