整潔架構SOLID-單一職責原則(SRP)

文章目錄

  • 定義
  • 案例分析
    • 重復的假象
    • 代碼合并
    • 解決方案
  • 小結

定義

SRP是SOLID五大設計原則中最容易被誤解的一個。也許是名字的原因,很多程序員根據SRP這個名字想當然地認為這個原則就是指:每個模塊都應該只做一件事

在歷史上,我們曾經這樣描述SRP這一設計原則:

任何一個軟件模塊都應該有且僅有一個被修改的原因

在現實環境中,軟件系統為了滿足用戶和所有者的要求,必然要經常做出這樣那樣的修改。而該系統的用戶或者所有者就是該設計原則中所指的“被修改的原因”。所以,我們也可以這樣描述SRP:

任何一個軟件模塊都應該只對一個用戶(User)或系統利益相關者(Stakeholder)負責

不過,這里的“用戶”和“系統利益相關者”在用詞上也并不完全準確,它們很有可能指的是一個或多個用戶和利益相關者,只要這些人希望對系統進行的變更是相似的,就可以歸為一類——一個或多個有共同需求的人。在這里,我們將其稱為行為者(actor)。

所以,對于SRP的最終描述就變成了:

任何一個軟件模塊都應該只對某一類行為者負責。

案例分析

重復的假象

某個工資管理程序中的Employee類有三個函數calculatePay()、reportHours()和save()
在這里插入圖片描述

如上圖所示這個類的三個函數分別對應的是三類非常不同的行為者,違反了SRP設計原則。

  • calculatePay()函數是由財務部門制定的,他們負責向CFO匯報。
  • reportHours()函數是由人力資源部門制定并使用的,他們負責向COO匯報。
  • save()函數是由DBA制定的,他們負責向CTO匯報。

這三個函數被放在同一個源代碼文件,即同一個Employee類中,程序員這樣做實際上就等于使三類行為者的行為耦合在了一起,這有可能會導致CFO團隊的命令影響到COO團隊所依賴的功能

例如,calculatePay()函數和reportHours()函數使用同樣的邏輯來計算正常工作時數。程序員為了避免重復編碼,通常會將該算法單獨實現為一個名為regularHours()的函數:
在這里插入圖片描述

接下來,假設CFO團隊需要修改正常工作時數的計算方法,而COO帶領的HR團隊不需要這個修改,因為他們對數據的用法是不同的。這時候,負責這項修改的程序員會注意到calculatePay()函數調用了regularHours()函數,但可能不會注意到該函數會同時被reportHours()調用。

這類問題發生的根源就是因為我們將不同行為者所依賴的代碼強湊到了一起。對此,SRP強調這類代碼一定要被分開。

代碼合并

一個擁有很多函數的源代碼文件必然會經歷很多次代碼合并,該文件中的這些函數分別服務不同行為者的情況就更常見了。

例如,CTO團隊的DBA決定要對Employee數據庫表結構進行簡單修改。與此同時,COO團隊的HR需要修改工作時數報表的格式。

這樣一來,就很可能出現兩個來自不同團隊的程序員分別對Employee類進行修改的情況。不出意外的話,他們各自的修改一定會互相沖突,這就必須要進行代碼合并

在這個例子中,這次代碼合并不僅有可能讓CTO和COO要求的功能出錯,甚至連CFO原本正常的功能也可能受到影響。

多人為了不同的目的修改了同一份源代碼,這很容易造成問題的產生。

解決方案

最簡單直接的辦法是將數據與函數分離,設計三個類共同使用一個不包括函數的、十分簡單的EmployeeData類,每個類只包含與之相關的函數代碼,互相不可見,這樣就不存在互相依賴的情況了。
在這里插入圖片描述

這種解決方案的壞處在于:程序員現在需要在程序里處理三個類。另一種解決辦法是使用Facade設計模式:
在這里插入圖片描述

這樣一來,EmployeeFacade類所需要的代碼量就很少了,它僅僅包含了初始化和調用三個具體實現類的函數。

我們也可以選擇將最重要的函數保留在Employee類中,同時用這個類來調用其他沒那么重要的函數:
在這里插入圖片描述

總而言之,上面的每一個類都分別容納了一組作用于相同作用域的函數,而在該作用域之外,它們各自的私有函數是互相不可見的。

小結

單一職責原則主要討論的是函數和類之間的關系—但是它在兩個討論層面上會以不同的形式出現。在組件層面,我們可以將其稱為共同閉包原則(Common Closure Principle),在軟件架構層面,它則是用于奠定架構邊界的變更軸心(Axis ofChange)。

參考內容來源于:《架構整潔之道》

本文來自互聯網用戶投稿,該文觀點僅代表作者本人,不代表本站立場。本站僅提供信息存儲空間服務,不擁有所有權,不承擔相關法律責任。
如若轉載,請注明出處:http://www.pswp.cn/web/40555.shtml
繁體地址,請注明出處:http://hk.pswp.cn/web/40555.shtml
英文地址,請注明出處:http://en.pswp.cn/web/40555.shtml

如若內容造成侵權/違法違規/事實不符,請聯系多彩編程網進行投訴反饋email:809451989@qq.com,一經查實,立即刪除!

相關文章

科研繪圖系列:R語言雙側條形圖(bar Plot)

介紹 雙側條形圖上的每個條形代表一個特定的細菌屬,條形的高度表示該屬的LDA得分的對數值,顏色用來區分不同的分類群或組別,它具有以下優點: 可視化差異:條形圖可以直觀地展示不同細菌屬在得分上的差異。強調重要性:較高的條形表示某些特征在區分不同組別中具有重要作用…

# Sharding-JDBC從入門到精通(6)-- Sharding-JDBC 水平分庫 和 垂直分庫。

Sharding-JDBC從入門到精通&#xff08;6&#xff09;-- Sharding-JDBC 水平分庫 和 垂直分庫。 一、Sharding-JDBC 水平分庫-分片策略配置 1、分庫策略定義方式如下 # 分庫策略&#xff0c;如何將一個邏輯表映射到多個數據源 spring.shardingsphere.sharding.tables.<邏…

第33集《大乘起信論》

《大乘起信論》和尚尼慈悲&#xff0c;諸位法師、諸位居士&#xff0c;阿彌陀佛&#xff01;&#xff08;阿彌陀佛&#xff01;&#xff09;請大家打開《講義》第七十四頁&#xff0c;子二、釋觀。 本論的特色&#xff0c;一言以蔽之就是文簡意賅、辭約理富&#xff0c;就是說…

VUE2拖拽組件:vue-draggable-resizable-gorkys

vue-draggable-resizable-gorkys組件基于vue-draggable-resizable進行二次開發, 用于可調整大小和可拖動元素的組件并支持沖突檢測、元素吸附、元素對齊、輔助線 安裝: npm install --save vue-draggable-resizable-gorkys 全局引用: import Vue from vue import vdr fro…

嵌入式linux面試1

1. linux 1.1. Window系統和Linux系統的區別 linux區分大小寫windows在dos&#xff08;磁盤操作系統&#xff09;界面命令下不區分大小寫&#xff1b; 1.2. 文件格式區分 windows用擴展名區分文件&#xff1b;如.exe代表執行文件&#xff0c;.txt代表文本文件&#xff0c;.…

運用Python與Keras框架打造深度學習圖像分類應用:詳盡步驟與代碼實例解析

引言 隨著深度學習技術的飛速發展&#xff0c;其在圖像識別和分類領域的應用日益廣泛。在這一背景下&#xff0c;Python因其豐富的數據科學庫和強大的生態系統而成為首選編程語言之一。在本文中&#xff0c;我們將深入探討如何使用Python和其中的Keras深度學習框架來完成一個實…

手動將dingtalk-sdk-java jar包打入maven本地倉庫

有時候,中央鏡像庫不一定有自己需要的jar包,這時候我們就需要用到該方法,將jar打入maven本地倉庫,然后項目中,正常使用maven的引入規則。 mvn install:install-file -Dmaven.repo.local=D:\software\maven\apache-maven-3.6.3-bin\apache-maven-3.6.3\repo -DgroupId=ding…

學習筆記——交通安全分析11

目錄 前言 當天學習筆記整理 4信控交叉口交通安全分析 結束語 前言 #隨著上一輪SPSS學習完成之后&#xff0c;本人又開始了新教材《交通安全分析》的學習 #整理過程不易&#xff0c;喜歡UP就點個免費的關注趴 #本期內容接上一期10筆記 #最近確實太懶了&#xff0c;接受…

跨越數據邊界:域適應在目標檢測中的革新作用

標題&#xff1a;跨越數據邊界&#xff1a;域適應在目標檢測中的革新作用 在機器學習和計算機視覺領域&#xff0c;尤其是目標檢測任務中&#xff0c;域適應&#xff08;Domain Adaptation&#xff09;是一種關鍵技術&#xff0c;它解決了模型在不同數據分布上的泛化問題。當訓…

C語言字節對齊技術在嵌入式、網絡與操作系統中的應用與優化

第一部分&#xff1a;嵌入式系統中的字節對齊 嵌入式系統通常對性能和資源有著嚴格的要求。在這些系統中&#xff0c;字節對齊的正確使用可以顯著提高數據訪問速度&#xff0c;減少內存占用&#xff0c;并提高系統的整體效率。 一、嵌入式系統中的字節對齊挑戰 嵌入式系統中…

Caffeinated for Mac v2.0.6 Mac防休眠應用 兼容 M1/M2/M3

Caffeinated 可以防止您的 Mac 進入休眠狀態、屏幕變暗或者啟動屏幕保護。 應用介紹 您的屏幕是否總是在您不希望的時候變暗&#xff1f;那么Caffeinated就是您解決這個大麻煩的最好工具啦。Caffeinated是在Caffeine這個非常便捷、有用的工具的基礎上開發而來的。Caffeinated…

215. 數組中的第K個最大元素(中等)

215. 數組中的第K個最大元素 1. 題目描述2.詳細題解3.代碼實現3.1 Python3.2 Java 1. 題目描述 題目中轉&#xff1a;215. 數組中的第K個最大元素 2.詳細題解 快速排序算法在每一輪排序中&#xff0c;隨機選擇一個數字 x x x&#xff0c;根據與 x x x的大小關系將要排序的數…

PMP–知識卡片--PDCA循環

記憶 PDCA&#xff1a;計劃執行檢查調整&#xff0c;計劃觀察動作&#xff1b;plan do check action 定義 PDCA循環的含義是將質量管理分為四個過程&#xff0c;即計劃&#xff08;Plan&#xff09;、執行&#xff08;Do&#xff09;、檢查&#xff08;Check&#xff09;、處…

C++開發調試工具:GDB調試,windebug調試,adb調試

我們在C開發過程中時常避免不了要調試追蹤&#xff0c;一下介紹最主流的三種調試工具&#xff1a; 一.GDB調試 1.coredump文件&#xff1a; coredump文件是程序異常時系統產生的錯誤日志文件&#xff0c;即核心轉儲文件&#xff1b; 編譯一個debug程序&#xff0c;必須是debu…

使用 OpenCV 和 Python 進行車道檢測和物體檢測(YOLO)

本項目旨在開發一個集車道檢測與物體檢測功能于一體的智能視覺分析系統&#xff0c;利用先進的計算機視覺技術和深度學習模型&#xff0c;實現實時的道路場景理解和目標識別。系統主要依托OpenCV這一強大的計算機視覺庫&#xff0c;以及Python作為編程語言&#xff0c;融合了車…

MySQL索引教程(01):創建索引

文章目錄 MySQL 創建索引索引介紹MySQL CREATE INDEX 語法MySQL 索引類型MySQL CREATE INDEX 實例結論 MySQL 創建索引 對于一個具有大量數據行的表&#xff0c;如果你根據某個查詢條件檢索數據時很慢&#xff0c;可能是因為你沒有在檢索條件相關的列上創建索引。 索引類似于…

FPC生產工藝全流程詳解

FPC生產制作繁瑣而且難度較大&#xff0c;與普通PCB比較&#xff0c;FPC單位面積電路的造價高很多&#xff0c;但是&#xff0c;由于FPC優異的柔性、輕薄和可靠性等特性&#xff0c;給眾多領域的設備和產品提供了更廣泛的實現空間和新的設計方案&#xff0c;比如沉金板在電子、…

android的activty冷啟動和熱啟動差異是什么?

Android的Activity冷啟動和熱啟動之間存在顯著差異&#xff0c;這些差異主要體現在啟動過程、資源加載、組件初始化以及用戶體驗等方面。以下是對兩者差異的詳細分析&#xff1a; 一、定義與過程差異 冷啟動&#xff1a; 定義&#xff1a;冷啟動是指應用程序完全退出后&#…

Java需要英語基礎嗎?

Java編程語言本身并不要求必須有很強的英語基礎&#xff0c;因為Java的語法和邏輯是獨立于任何特定語言的。我收集歸類了一份嵌入式學習包&#xff0c;對于新手而言簡直不要太棒&#xff0c;里面包括了新手各個時期的學習方向編程教學、問題視頻講解、畢設800套和語言類教學&am…

android開發引入jar包

我在為一個安卓設備開發一個APP&#xff0c;設備的廠家給我提供了一個jar包&#xff0c;我應該如何把它引入到項目之中呢&#xff1f; 很慚愧我以前幾乎沒做過android的開發&#xff0c;在此之前這么一個簡單的問題也不會。 實踐 我隨手在Android studio中新建了一個項目。 你…