成人免费xxxxx在线视频软件_久久精品久久久_亚洲国产精品久久久_天天色天天色_亚洲人成一区_欧美一级欧美三级在线观看

偷偷看了同事的代碼找到了優(yōu)雅代碼的秘密

開發(fā) 后端
本文總結(jié)了軟件代碼設(shè)計(jì)中的五大原則,按照我自己的理解,這五大原則就是程序猿代碼設(shè)計(jì)的內(nèi)功,而二十三種設(shè)計(jì)模式實(shí)際就是內(nèi)功催生出來(lái)的編程招式,因此深入理解五大設(shè)計(jì)原則是我們用好設(shè)計(jì)模式的基礎(chǔ),也是我們?cè)谄綍r(shí)設(shè)計(jì)代碼結(jié)構(gòu)的時(shí)候需要遵循的一些常見規(guī)范。

引言

對(duì)于一個(gè)軟件平臺(tái)來(lái)說(shuō),軟件平臺(tái)代碼的好壞直接影響平臺(tái)整體的質(zhì)量與穩(wěn)定性。同時(shí)也會(huì)影響著寫代碼同學(xué)的創(chuàng)作激情。想象一下如果你從git上面clone下來(lái)的的工程代碼亂七八糟,代碼晦澀難懂,難以快速入手,有種想推到重寫的沖動(dòng),那么程序猿在這個(gè)工程中寫好代碼的初始熱情都沒了。相反,如果clone下的代碼結(jié)構(gòu)清晰,代碼優(yōu)雅易懂,那么你在寫代碼的時(shí)候都不好意思寫爛代碼。這其中的差別相信工作過(guò)的同學(xué)都深有體會(huì),那么我們看了那么多代碼之后,到底什么樣的代碼才是好代碼呢?它們有沒有一些共同的特征或者原則?本文通過(guò)闡述優(yōu)雅代碼的設(shè)計(jì)原則來(lái)和大家聊聊怎么寫好代碼。

代碼設(shè)計(jì)原則

好代碼是設(shè)計(jì)出來(lái)的,也是重構(gòu)出來(lái)的,更是不斷迭代出來(lái)的。在我們接到需求,經(jīng)過(guò)概要設(shè)計(jì)過(guò)后就要著手進(jìn)行編碼了。但是在實(shí)際編碼之前,我們還需要進(jìn)行領(lǐng)域分層設(shè)計(jì)以及代碼結(jié)構(gòu)設(shè)計(jì)。那么怎么樣才能設(shè)計(jì)出來(lái)比較優(yōu)雅的代碼結(jié)構(gòu)呢?有一些大神們總結(jié)出來(lái)的優(yōu)雅代碼的設(shè)計(jì)原則,我們分別來(lái)看下。

SRP

所謂SRP(Single Responsibility Principle)原則就是職責(zé)單一原則,從字面意思上面好像很好理解,一看就知道什么意思。但是看的會(huì)不一定就代表我們就會(huì)用,有的時(shí)候我們以為我們自己會(huì)了,但是在實(shí)際應(yīng)用的時(shí)候又會(huì)遇到這樣或者那樣的問(wèn)題。原因就是實(shí)際我們沒有把問(wèn)題想透,沒有進(jìn)行深度思考,知識(shí)還只是知識(shí),并沒有轉(zhuǎn)化為我們的能力。就比如這里所說(shuō)的職責(zé)單一原則指的是誰(shuí)的單一職責(zé),是類還是模塊還是域呢?域可能包含多個(gè)模塊,模塊也可以包含多個(gè)類,這些都是問(wèn)題。

為了方便進(jìn)行說(shuō)明,這里以類來(lái)進(jìn)行職責(zé)單一設(shè)計(jì)原則的說(shuō)明。對(duì)于一個(gè)類來(lái)說(shuō),如果它只負(fù)責(zé)完成一個(gè)職責(zé)或者功能,那么我們可以說(shuō)這個(gè)類時(shí)符合單一職責(zé)原則。請(qǐng)大家回想一下,其實(shí)我們?cè)趯?shí)際的編碼過(guò)程中,已經(jīng)有意無(wú)意的在使用單一職責(zé)設(shè)計(jì)原則了。因?yàn)閷?shí)際它是符合我們?nèi)怂伎紗?wèn)題的方式的。為什么這么說(shuō)呢?想想我們?cè)谡硪鹿竦臅r(shí)候,為了方便拿衣服我們會(huì)把夏天的衣服放在一個(gè)柜子中,冬天的衣服放在一個(gè)柜子。這樣季節(jié)變化的時(shí)候,我們只要到對(duì)應(yīng)的柜子直接拿衣服就可以了。否則如果冬天和夏天的衣服都放在一個(gè)柜子中,我們找衣服的時(shí)候可就費(fèi)勁了。放到軟件代碼設(shè)計(jì)中,我們也需要采用這樣的分類思維。在進(jìn)行類設(shè)計(jì)的時(shí)候,要設(shè)計(jì)粒度小、功能單一的類,而不是大而全的類。

舉個(gè)栗子,在學(xué)生管理系統(tǒng)中,如果一個(gè)類中既有學(xué)生信息的操作比如創(chuàng)建或者刪除動(dòng)作,又有關(guān)于課程的創(chuàng)建以及修改動(dòng)作,那么我們可以認(rèn)為這個(gè)類時(shí)不滿足單一職責(zé)的設(shè)計(jì)原則的,因?yàn)樗鼘蓚€(gè)不同業(yè)務(wù)域的業(yè)務(wù)混雜在了一起,所以我們需要進(jìn)行拆分,將這個(gè)大而全的類拆分為學(xué)生以及課程兩個(gè)業(yè)務(wù)域,這樣粒度更細(xì),更加內(nèi)聚。

筆者根據(jù)自身的經(jīng)驗(yàn),總結(jié)了需要考慮進(jìn)行單一職責(zé)拆分的幾個(gè)原則,希望對(duì)大家判斷是否需要進(jìn)行拆分有個(gè)簡(jiǎn)單的判斷的標(biāo)準(zhǔn):

1、不同的業(yè)務(wù)域需要進(jìn)行拆分,就像上面的例子,另外如果與其他類的依賴過(guò)多,也需要考慮是不是應(yīng)該進(jìn)行拆分;

2、如果我們?cè)陬愔芯帉懘a的時(shí)候發(fā)現(xiàn)私有方法具有一定的通用性,比如判斷ip是不是合法,解析xml等,那我們可以考慮將這些方法抽出來(lái)形成公共的工具類,這樣其他類也可以方便的進(jìn)行使用。

另外單一職責(zé)的設(shè)計(jì)思想不止在代碼設(shè)計(jì)中使用,我們?cè)谶M(jìn)行微服務(wù)拆分的時(shí)候也會(huì)一定程度的遵循這個(gè)原則。

OCP

OCP(Open Closed Principle)即對(duì)修改關(guān)閉,對(duì)擴(kuò)展開放原則,個(gè)人覺得這是設(shè)計(jì)原則中最難的原則。不僅理解起來(lái)有一定的門檻,在實(shí)際編碼過(guò)程中也是不容易做到的。

首先我們得先搞清楚這里的所說(shuō)的修改以及擴(kuò)展的區(qū)別在什么地方,說(shuō)實(shí)話一開始看到這個(gè)原則的時(shí)候,我總覺得修改和開放說(shuō)的不是一個(gè)意思嘛?想來(lái)想去都覺得有點(diǎn)迷糊。后來(lái)在不斷的項(xiàng)目實(shí)踐中,對(duì)這個(gè)設(shè)計(jì)原則的理解逐漸加深了。

設(shè)計(jì)原則中所說(shuō)的修改指的是對(duì)原有代碼的修改,而擴(kuò)展指的是在原有代碼基礎(chǔ)上的能力的擴(kuò)展,并不修改原先已有的代碼。這是修改與擴(kuò)展的最大的區(qū)別,一個(gè)需要修改原來(lái)的代碼邏輯,另一個(gè)不修改。因此才叫對(duì)修改關(guān)閉但是對(duì)擴(kuò)展開放。弄清楚修改和擴(kuò)展的區(qū)別之后,我們?cè)傧胍幌霝槭裁匆獙?duì)修改關(guān)閉,而要對(duì)擴(kuò)展開放呢?我們都知道軟件平臺(tái)都是不斷進(jìn)行更新迭代的,因此我們需要不斷在原先的代碼中進(jìn)行開發(fā)。那么就會(huì)涉及到一個(gè)問(wèn)題如果我們的代碼設(shè)計(jì)的不好,擴(kuò)展性不強(qiáng),那么每次進(jìn)行功能迭代的時(shí)候都會(huì)修改原先已有的代碼,有修改就有可能引入bug,造成系統(tǒng)平臺(tái)的不穩(wěn)定。因此我們?yōu)榱似脚_(tái)的穩(wěn)定性,需要對(duì)修改關(guān)閉。但是我們要添加新的功能怎么辦呢?那就是通過(guò)擴(kuò)展的方式來(lái)進(jìn)行,因此需要實(shí)現(xiàn)對(duì)擴(kuò)展開放。

這里我們以一個(gè)例子來(lái)進(jìn)行說(shuō)明,否則可能還是有點(diǎn)抽象。在一個(gè)監(jiān)控平臺(tái)中,我們需要對(duì)服務(wù)所占用CPU、內(nèi)存等運(yùn)行信息進(jìn)行監(jiān)控,第一版代碼如下。

public class Alarm {
private AlarmRule alarmRule;
private AlarmNotify alarmNotify;
public Alarm(AlarmRule alarmRule, AlarmNotify alarmNotify) {
this.alarmRule = alarmRule;
this.alarmNotify = alarmNotify;
}
public void checkServiceStatus(String serviecName, int cpu, int memory) {
if(cpu > alarmRule.getRule(ServiceConstant.Status).getCpuThreshold) {
alarmNotify.notify(serviecName + alarmRule.getRule(ServiceConstant.Status).getDescription)
}
if(memory > alarmRule.getRule(ServiceConstant.Status).getMemoryThreshold) {
alarmNotify.notify(serviecName + alarmRule.getRule(ServiceConstant.Status).getDescription)
}
}
}

代碼邏輯很簡(jiǎn)單,就是根據(jù)對(duì)應(yīng)的告警規(guī)則中的閾值判斷是否達(dá)到觸發(fā)告警通知的條件。如果此時(shí)來(lái)了個(gè)需求,需要增加判斷的條件,就是根據(jù)服務(wù)對(duì)應(yīng)的狀態(tài),判斷需不需要進(jìn)行告警通知。我們來(lái)先看下比較low的修改方法。我們?cè)赾heckServiceStatus方法中增加了服務(wù)狀態(tài)的參數(shù),同時(shí)在方法中增加了判斷狀態(tài)的邏輯。

public class Alarm {
private AlarmRule alarmRule;
private AlarmNotify alarmNotify;

public Alarm(AlarmRule alarmRule, AlarmNotify alarmNotify) {
this.alarmRule = alarmRule;
this.alarmNotify = alarmNotify;
}
public void checkServiceStatus(String serviecName, int cpu, int memory, int status) {
if(cpu > alarmRule.getRule(ServiceConstant.Status).getCpuThreshold) {
alarmNotify.notify(serviecName + alarmRule.getRule(ServiceConstant.Status).getDescription)
}
if(memory > alarmRule.getRule(ServiceConstant.Status).getMemoryThreshold) {
alarmNotify.notify(serviecName + alarmRule.getRule(ServiceConstant.Status).getDescription)
}
if(status == alarmRule.getRule(ServiceConstant.Status).getStatusThreshold) {
alarmNotify.notify(serviecName + alarmRule.getRule(ServiceConstant.Status).getDescription)
}
}
}

很顯然這種修改方法非常的不友好,為什么這么說(shuō)呢?首先修改了方法參數(shù),那么調(diào)用該方法的地方可能也需要修改,另外如果改方法有單元測(cè)試方法的話,單元測(cè)試用例必定也需要修改,在原有測(cè)試過(guò)的代碼中添加新的邏輯,也增加了bug引入的風(fēng)險(xiǎn)。因此這種修改的方式我們需要進(jìn)行避免。那么怎么修改才能夠體現(xiàn)對(duì)修改關(guān)閉以及對(duì)擴(kuò)展開放呢?

首先我們可以先將關(guān)于服務(wù)狀態(tài)的屬性抽象為一個(gè)ServiceStatus 實(shí)體,在對(duì)應(yīng)的檢查方法中以ServiceStatus 為入?yún)ⅲ@樣以后如果還有服務(wù)狀態(tài)的屬性增加的話,只需要在ServiceStatus 中添加即可,并不需要修改方法中的參數(shù)以及調(diào)用方法的地方,同樣單元測(cè)試的方法也不用修改。

@Data
public class ServiceStatus {
String serviecName;
int cpu;
int memory;
int status;

}

另外在檢測(cè)方法中,我們?cè)趺葱薷牟拍荏w現(xiàn)可擴(kuò)展呢?而不是在檢測(cè)方法中添加處理邏輯。一個(gè)比較好的實(shí)現(xiàn)方式就是通過(guò)抽象檢測(cè)方法,具體的實(shí)現(xiàn)在各個(gè)實(shí)現(xiàn)類中。這樣即使新增檢測(cè)邏輯,只需要擴(kuò)展檢測(cè)實(shí)現(xiàn)方法就可,不需要在修改原先代碼的邏輯,實(shí)現(xiàn)代碼的可擴(kuò)展。

LSP

LSP(Liskov Substitution Principle)里氏替換原則,這個(gè)設(shè)計(jì)原則我覺得相較于前面的兩個(gè)設(shè)計(jì)原則來(lái)說(shuō)要簡(jiǎn)單些。它的內(nèi)容為子類對(duì)象(object of subtype/derived class)能夠替換程序(program)中父類對(duì)象(object of base/parent class)出現(xiàn)的任何地方,并且保證原來(lái)程序的邏輯行為(behavior)不變及正確性不被破壞。

里式替換原則是用來(lái)指導(dǎo),繼承關(guān)系中子類該如何設(shè)計(jì)的一個(gè)原則。理解里式替換原則,最核心的就是理解“design by contract,按照協(xié)議來(lái)設(shè)計(jì)”這幾個(gè)字。父類定義了函數(shù)的“約定”(或者叫協(xié)議),那子類可以改變函數(shù)的內(nèi)部實(shí)現(xiàn)邏輯,但不能改變函數(shù)原有的“約定”。這里的約定包括:函數(shù)聲明要實(shí)現(xiàn)的功能;對(duì)輸入、輸出、異常的約定;甚至包括注釋中所羅列的任何特殊說(shuō)明。

我們?cè)趺磁袛嘤袥]有違背LSP呢?我覺得有兩個(gè)關(guān)鍵點(diǎn)可以作為判斷的依據(jù),一個(gè)是子類有沒有改變父類申明需要實(shí)現(xiàn)的業(yè)務(wù)功能,另一個(gè)是否違反父類關(guān)于輸入、輸出以及異常拋出的規(guī)定。

ISP

ISP(Interface Segregation Principle)接口隔離原則,簡(jiǎn)單理解就是只給調(diào)用方需要的接口,它不需要的就不要硬塞給他了。這里我們舉個(gè)栗子,以下是關(guān)于產(chǎn)品的接口,其中包含了創(chuàng)建產(chǎn)品、刪除產(chǎn)品、根據(jù)ID獲取產(chǎn)品以及更新產(chǎn)品的接口。如果此時(shí)我們需要對(duì)外提供一個(gè)根據(jù)產(chǎn)品的類別獲取產(chǎn)品的接口,我們應(yīng)該怎么辦?很多同學(xué)會(huì)說(shuō),這還不簡(jiǎn)單,我們直接在這個(gè)接口里面添加根據(jù)類別查詢產(chǎn)品的接口就OK了啊。大家想想這個(gè)方案有沒有什么問(wèn)題。

public interface ProductService { 
boolean createProduct(Product product);
boolean deleteProductById(long id);
Product getProductById(long id);
int updateProductInfo(Product product);
}
public class UserServiceImpl implements UserService { //...}

這個(gè)方案看上去沒什么問(wèn)題,但是再往深處想一想,外部系統(tǒng)只需要一個(gè)根據(jù)產(chǎn)品類別查詢商品的功能,,但是實(shí)際我們提供的接口中還包含了刪除、更新商品的接口。如果這些接口被其他系統(tǒng)誤調(diào)了可能會(huì)導(dǎo)致產(chǎn)品信息的刪除或者誤更新。因此我們可以將這些第三方調(diào)用的接口都隔離出來(lái),這樣就不存在誤調(diào)用以及接口能力被無(wú)序擴(kuò)散的情況了。

public interface ProductService { 
boolean createProduct(Product product);
boolean deleteProductById(long id);
Product getProductById(long id);
int updateProductInfo(Product product);
}
public interface ThirdSystemProductService{
List<Product> getProductByType(int type);
}
public class UserServiceImpl implements UserService { //...}

LOD

LOD(Law of Demeter)即迪米特法則,這是我們要介紹的最后一個(gè)代碼設(shè)計(jì)法則了,光從名字上面上看,有點(diǎn)不明覺厲的感覺,看不出來(lái)到底到底想表達(dá)什么意思。我們可以來(lái)看下原文是怎么描述這個(gè)設(shè)計(jì)原則的。

Each unit should have only limited knowledge about other units: only units “closely” related to the current unit. Or: Each unit should only talk to its friends; Don’t talk to strangers.

按照我自己的理解,這迪米特設(shè)計(jì)原則的最核心思想或者說(shuō)最想達(dá)到的目的就是盡最大能力減小代碼修改帶來(lái)的對(duì)原有的系統(tǒng)的影響。所以需要實(shí)現(xiàn)類、模塊或者服務(wù)能夠?qū)崿F(xiàn)高內(nèi)聚、低耦合。不該有直接依賴關(guān)系的類之間,不要有依賴;有依賴關(guān)系的類之間,盡量只依賴必要的接口。迪米特法則是希望減少類之間的耦合,讓類越獨(dú)立越好。每個(gè)類都應(yīng)該少了解系統(tǒng)的其他部分。一旦發(fā)生變化,需要了解這一變化的類就會(huì)比較少。打個(gè)比方這就像抗戰(zhàn)時(shí)期的的地下組織一樣,相關(guān)聯(lián)的聚合到一起,但是與外部保持盡可能少的聯(lián)系,也就是低耦合。

總結(jié)

本文總結(jié)了軟件代碼設(shè)計(jì)中的五大原則,按照我自己的理解,這五大原則就是程序猿代碼設(shè)計(jì)的內(nèi)功,而二十三種設(shè)計(jì)模式實(shí)際就是內(nèi)功催生出來(lái)的編程招式,因此深入理解五大設(shè)計(jì)原則是我們用好設(shè)計(jì)模式的基礎(chǔ),也是我們?cè)谄綍r(shí)設(shè)計(jì)代碼結(jié)構(gòu)的時(shí)候需要遵循的一些常見規(guī)范。只有不斷的在設(shè)計(jì)代碼-》遵循規(guī)范-》編寫代碼-》重構(gòu)這個(gè)循環(huán)中磨礪,我們才能編寫出優(yōu)雅的代碼。




責(zé)任編輯:姜華 來(lái)源: 慕楓技術(shù)筆記
相關(guān)推薦

2021-01-04 13:33:08

黑客微軟網(wǎng)絡(luò)攻擊

2020-05-15 09:30:12

代碼函數(shù)語(yǔ)言

2023-05-28 12:23:59

ChatGPT中文數(shù)據(jù)集

2022-10-20 07:57:32

高層模塊設(shè)計(jì)代碼

2025-04-02 12:20:00

開發(fā)代碼函數(shù)

2014-02-28 13:46:35

Angular代碼

2024-06-24 14:19:48

2021-12-20 10:54:47

智能華為汽車

2022-03-23 08:01:04

Python語(yǔ)言代碼

2023-02-15 08:30:05

2022-05-24 06:07:48

JShack用戶代碼

2022-08-01 23:45:23

代碼識(shí)別項(xiàng)目

2019-06-24 10:26:15

代碼程序注釋

2021-12-03 11:57:27

代碼##語(yǔ)言

2024-12-12 12:00:00

代碼C++

2024-02-23 08:57:42

Python設(shè)計(jì)模式編程語(yǔ)言

2019-09-20 15:47:24

代碼JavaScript副作用

2022-03-11 12:14:43

CSS代碼前端

2023-07-30 22:25:00

JavaScrip服務(wù)端Web

2021-01-04 07:57:07

C++工具代碼
點(diǎn)贊
收藏

51CTO技術(shù)棧公眾號(hào)

主站蜘蛛池模板: 96久久久久久 | 欧美福利一区 | 国产精品视频一区二区三区不卡 | 亚洲精品在线免费观看视频 | 在线黄色影院 | 少妇av片 | 婷婷久久网 | 亚洲国产一区在线 | 日韩欧美精品一区 | 男人天堂久久 | 成人永久免费视频 | 91精品一区二区 | 视频一区在线观看 | 久久久这里都是精品 | 成人影视网址 | 久久高清 | 国产精品久久久久影院色老大 | 99爱在线免费观看 | 久久久.com | 黄色亚洲网站 | 亚洲成人免费 | 久久久久成人精品免费播放动漫 | 亚洲国产精品一区二区www | 欧洲一级毛片 | 皇色视频在线 | 青青草一区 | 超碰人人人 | 美女国产精品 | 欧美成视频 | 亚洲美女一区 | 天堂av免费观看 | 九九九视频在线观看 | 91在线观| 国产ts人妖另类 | 久久久国产精品入口麻豆 | 亚洲高清av | 一本色道精品久久一区二区三区 | 欧美在线视频一区 | 日韩成人免费 | 97久久精品午夜一区二区 | 国产亚洲一区二区三区在线观看 |