--- tags: 教學中心 --- # GAS 軟體設計 https://hackmd.io/@zxcj04/GAS_SD [TOC] ## Interface - 「統一的」、「標準的」規格 <!-- -  --> - | 介面 | USB | 插座 | | :----: | :----: | :----: | | | 隨身碟 | 吹風機 | | | 光碟機 | 吸塵器 | ## Abstraction 只描述一個大概的流程跟邏輯,真正實現的方法交由底下各個裝置去做 ```java interface USBInterface { /** 裝置開機 */ public function boot(); /** 裝置是否有連線 */ public function isConnected(); /** 裝置連線不成功的錯誤訊息 */ public function getErrorMessage(); /** 裝置取得電源 */ public function getPower(); /** 裝置取得需要使用到的資料 */ public function getData(); /** 裝置把資料儲存起來 */ public function saveData(); /** 裝置關機 */ public function shutdown(); } ``` 實做 ```java class Mouse implements USBInterface { /** 實作 USB 滑鼠的開啟方法 */ public function boot() { if ( $this->isBoot() ) { return "滑鼠開啟成功"; } else { $this->bootRetry(); } } /** 實作其他方法 (略) */ ... } class Keyboard implements USBInterface { /** 實作 USB 鍵盤的開機方法 */ public function boot() { if ( $this->bluetoothConnect() ) { return "已連線到藍芽鍵盤"; } else { if ( $this->bootKeyboard() ) { return "鍵盤開啟成功" } } } /** 實作其他方法 (略) */ ... } ``` ## 耦合 內聚 - 耦合(Coupling) - 兩個模組間的關連性或相依性 - 一個很小的需求異動,但是連帶影響到跟它有相依關係的部份 - 內聚(Cohesion) - 模組本身不需依賴其他模組,就能完成工作 - 低耦合、高內聚的目的,就是為了提升各模組功能的重用性、擴展性、維護性 `降低耦合性 提高內聚力` ## SOLID - 單一職責原則(Single responsibility principle, SRP) - 開放封閉原則(Open-close principle, OCP) - open for extension - closed for modification - 里氏替換原則(Liskov substitution principle, LSP) - 接口隔離原則(Interface segregation principle, ISP) - 依賴反轉原則(Dependency inversion principle, DIP) ## Bad Smell ### Duplicated Code - Modifiability(修改性) - Understandability(理解性) - Testability(可測性) - Resource usage(資源使用) ### Long Method(過長函數) - Explanation(解釋) - method 做了太多事 - long method 降低 understandability - Sharing(共享) - 即使其中一段程式碼有被重複使用的機會 但因為一個 method 作太多事 因此 reusability 降低 - Modifiability(可修改性) - Testability(可測性) ### Large Class(過大類別) - 參考 Long Method ### Long Parameter List(過長參數列) - Hard to understand(難以理解) - Inconsistent(不一致) - Difficult to use(難以使用) - Interface change(介面改變) - 有著過長參數列的函數 只要任何一個參數改變 或是需要增加新的參數 都會造成函數介面改變 ### Divergent Change(發散式修改) - 一個類別會因為多種不同的原因而造成其改變 違反了 Single Responsibility Principle(SRP) - Modifiability(修改性) - Understandability(可理解性) - Testability(可測性) - Reusability(重複使用性) ### Shotgun Surgery(霰彈式修改) - 某種修改會跨越多個類別 與 divergent change 剛好相反 某種責任分散在多個類別身上 - 大部份發生在 duplicated code 上 ### Feature Envy(特性依戀) example 一本電話簿,裡面有一些聯絡人,聯絡人存著姓名、email,與電話。每當我需要時,就要得到特定格式的『聯絡人清單』。 ```java // Contact.java public class Contact { private String name; private String email; private String phoneNumber; public Contact(String name, String email, String phoneNumber) { this.name = name; this.email = email; this.phoneNumber = phoneNumber; } // ...後略 } // PhoneBook.java public class PhoneBook { List<Contact> contacts; public PhoneBook() { this.contacts = new ArrayList<>(); } public String generateFormattedPrint(){ String result = ""; for (Contact contact : contacts){ result += contact.getName() + ": "; result += contact.getEmail() + " | "; result += contact.getPhoneNumber() + ". "; result += "\n"; } return result; } // ...後略 } ``` 類別 PhoneBook 過度依賴 Contact 這個類別 它裡面使用的method全部都是Contact提供的 這件事情嚴重地違反了物件導向的單一職責原則(SRP) 若是聯絡人的內容與輸出格式一旦有換 需要同時更動 Contact 和 PhoneBook 應該修改成 ```java // Contact.java public class Contact { // ...前略 public String generateFormattedPrint(){ String result = name + ": "; result += email + " | "; result += phoneNumber + ". "; return result; } } // PhoneBook.java public class PhoneBook { List<Contact> contacts; public PhoneBook() { this.contacts = new ArrayList<>(); } public String generateFormattedPrint(){ String result = ""; for (Contact contact : contacts){ result += contact.generateFormattedPrint(); result += "\n"; } return result; } // ...後略 } ```
×
Sign in
Email
Password
Forgot password
or
By clicking below, you agree to our
terms of service
.
Sign in via Facebook
Sign in via Twitter
Sign in via GitHub
Sign in via Dropbox
Sign in with Wallet
Wallet (
)
Connect another wallet
New to HackMD?
Sign up