欧美bbbwbbbw肥妇,免费乱码人妻系列日韩,一级黄片

Java雜談之重復代碼是什么

 更新時間:2021年09月30日 17:32:11   作者:JavaEdge.  
剛開始工作時,總有人開玩笑說,編程實際上就是 CV,調侃很多程序員寫程序依靠的是復制粘貼。至今,很多初級甚至高級程序員寫代碼依舊是CV,就是把其他項目里的一段代碼復制過來,稍加改動,然后,跑一下沒有大問題就完事。這就是在給其他人挖坑

有經驗的程序員應該都見過,一個方法坐擁幾十上百個參數。

方法為何要有參數?

因為不同方法間需共享信息。

但方法間共享信息的方式不止一種,除了參數列表,還有全局變量。但全局變量總能帶來意外驚喜,所以,取消全局變量也是各大語言的趨勢。

但方法之間還是要傳遞信息的,不能用全局變量,于是參數就成了唯一選擇,于是,只要你想到有什么信息要傳給一個方法,就會直接它加到參數列表中,參數列表也越來越長。

長參數列表的問題

參數列表過長,你一個 crud 程序員就很難完全掌控這些邏輯了呀!

所以癥結是數量多,解決關鍵也就在于降低參數的數量。

解決方案

聚沙成塔

一個簡單的創(chuàng)建博客的方法:

public void createActicle(final String title, 
                       final String introduction,
                       final URL coverUrl,
                       final ActicleType type,
                       final ActicleColumn column,
                       final String protagonists,
                       final String tags,
                       final boolean completed) {
  ...
  Acticle acticle = Acticle.builder
    .title(title) 
    .introduction(introduction)
    .coverUrl(coverUrl)
    .type(type)
    .column(column)
    .protagonists(protagonists)
    .tags(tags)
    .completed(completed)
    .build();
    
  this.repository.save(acticle);
}

參數列表包含了一篇博客所要擁有的各種信息,比如:博客標題、博客簡介、封面 URL、博客類型、博客歸屬的專欄、主角姓名、博客標簽、博客是否完結…

如果只是想理解邏輯,或許你還會覺得參數列表挺合理,畢竟它把創(chuàng)建一篇博客所需的各種信息都傳給了方法,這也是大部分人面對一段代碼時理解問題的最初角度。
雖然這樣寫代碼容易讓人理解,但這不足以讓你發(fā)現問題。

現在產品要求在博客里增加一項信息,標識這部博客是否是簽約博客,也就是這部博客是否可收費,咋辦?

很簡單??!我直接新增一個參數。很多屎山就這么來的,積少成多,量變引起質變!

這里所有參數都是創(chuàng)建博客所必需的。所以,可以做的就是將這些參數封裝成一個類,一個創(chuàng)建博客的參數類:

public class NewActicleParamters {
  private String title;
  private String introduction;
  private URL coverUrl;
  private ActicleType type;
  private ActicleColumn column;
  private String protagonists;
  private String tags;
  private boolean completed;
  ...
}

這樣參數列表就只剩下一個參數了:

public void createActicle(final NewActicleParamters parameters) {
  ...
}

所以, 將參數列表封裝成對象吧 !

只是把一個參數列表封裝成一個類,然后,用到這些參數的時候,還需要把它們一個個取出來,這會不會是多此一舉呢?就像這樣:

public void createActicle(final NewActicleParamters parameters) {
  ...
  Acticle acticle = Acticle.builder
    .title(parameters.getTitle()) 
    .introduction(parameters.getIntroduction())
    .coverUrl(parameters.getCoverUrl())
    .type(parameters.getType())
    .channel(parameters.getChannel())
    .protagonists(parameters.getProtagonists())
    .tags(parameters.getTags())
    .completed(parameters.isCompleted())
    .build();
    
  this.repository.save(acticle);
}

若你也這樣想,說明:你還沒有形成對軟件設計的理解。我們并非簡單地把參數封裝成類,站在設計角度,這里引入的是一個新模型。
一個模型的封裝應該以【行為】為基礎。
之前沒有這個模型,所以想不到它應該有什么行為,現在模型產生了,它就該有自己配套的行為。

那這個模型的行為是什么?構建一個博客對象,這很清晰,則代碼就能進一步重構:

public class NewActicleParamters {
  private String title;
  private String introduction;
  private URL coverUrl;
  private ActicleType type;
  private ActicleColumn column;
  private String protagonists;
  private String tags;
  private boolean completed;
  
  public Acticle newActicle() {
    return Acticle.builder
      .title(title) 
      .introduction(introduction)
      .coverUrl(coverUrl)
      .type(type)
      .column(column)
      .protagonists(protagonists)
      .tags(tags)
      .completed(completed)
      .build();
  }
}

創(chuàng)建博客的方法就得到了極大簡化:

public void createActicle(final NewActicleParamters parameters) {
  ...
  Acticle acticle = parameters.newActicle();
    
  this.repository.save(acticle);
}

“如何擴展需求”?如果需求擴展,需要增加創(chuàng)建博客所需的內容,那這個參數列表就是不變的,相對來說,它就是穩(wěn)定的。

那這個類就會不斷膨脹,變成一個大類,那該怎么辦呢?如何解決大類?

動靜分離

不是所有情況下,參數都屬于一個類:

public void getChapters(final long acticleId, 
                        final HttpClient httpClient,
                        final ChapterProcessor processor) {
  HttpUriRequest request = createChapterRequest(acticleId);
  HttpResponse response = httpClient.execute(request);
  List<Chapter> chapters = toChapters(response);
  processor.process(chapters);
}

根據博客 ID 獲取其對應章節(jié)信息。
純以參數個數論,參數數量不多。

如果你只是看這個方法,可能很難發(fā)現直接問題。絕對數量不是關鍵點,參數列表也應該是越少越好。

在這幾個參數里面,每次傳進來的 acticleId 都不一樣,隨請求不同而改變。但 httpClient 和 processor 兩個參數一樣,因為都有相同邏輯,沒什么變化。
即acticleId 的變化頻率同 httpClient 和 processor 這兩個參數變化頻率不同。

不同的數據變動方向也是不同關注點。這里表現出來的就是典型的動數據(acticleId)和靜數據(httpClient 和 processor),它們是不同關注點,應該分離。

具體到這個場景下,靜態(tài)不變的數據完全可以成為這個方法所在類的一個字段,而只將每次變動的東西作為參數傳遞就可以了。按照這個思路,代碼可以改成這個樣子:

public void getChapters(final long acticleId) {
  HttpUriRequest request = createChapterRequest(acticleId);
  HttpResponse response = this.httpClient.execute(request);
  List<Chapter> chapters = toChapters(response);
  this.processor.process(chapters);
}

這個壞味道其實是一個軟件設計問題,代碼缺乏應有的結構,所以,原本應該屬于靜態(tài)結構的部分卻以動態(tài)參數的方式傳來傳去,無形之中拉長了參數列表。

長參數列表固然可以用一個類進行封裝,但能夠封裝出這個類的前提條件是:這些參數屬于一個類,有相同變化原因。

如果方法的參數有不同的變化頻率,就要視情況而定了。對于靜態(tài)的部分,我們前面已經看到了,它可以成為軟件結構的一篇分,而如果有多個變化頻率,我們還可以封裝出多個參數類。

告別標記

public void editChapter(final long chapterId, 
                        final String title, 
                        final String content, 
                        final boolean apporved) {
  ...
}

待修改章節(jié)的ID、標題和內容,最后一個參數表示這次修改是否直接審核通過。

前面幾個參數是修改一個章節(jié)的必要信息,重點在最后這個參數。
從業(yè)務上說,如果是作者進行編輯,之后要經過審核,而如果編輯來編輯的,那審核就直接通過,因為編輯本身扮演了審核人的角色。所以,你發(fā)現了,這個參數實際上是一個標記,標志著接下來的處理流程會有不同。

使用標記參數,是程序員初學編程時常用的一種手法。正是這種手法實在太好用,導致代碼里flag肆意飄蕩。不僅變量里有標記,參數里也有。很多長參數列表其中就包含了各種標記參數。

在實際的代碼中,必須小心翼翼地判斷各個標記當前的值,才能做好處理。

解決標記參數,一種簡單的方式就是,將標記參數代表的不同路徑拆分出來。

這里的一個方法可以拆分成兩個方法,一個方法負責“普通的編輯”,另一個負責“可以直接審核通過的編輯”。

// 普通的編輯,需要審核
public void editChapter(final long chapterId, 
                        final String title, 
                        final String content) {
  ...
}
// 直接審核通過的編輯
public void editChapterWithApproval(final long chapterId,
                                    final String title,
                                    final String content) {
 ...
}

標記參數在代碼中存在的形式很多,有的是布爾值、枚舉值、字符串或整數。都可以通過拆分方法的方式將它們拆開。在重構中,這種手法叫做移除標記參數(Remove Flag Argument)。

只有短小的代碼,我們才能有更好地把握,而要寫出短小的代碼,需要我們能夠“分離關注點”。

總結

應對長參數列表主要的方式就是減少參數的數量,最直接的就是將參數列表封裝成一個類。但并不是說所有的情況都能封裝成類來解決,我們還要分析是否所有的參數都有相同的變動頻率。

變化頻率相同,則封裝成一個類。
變化頻率不同的話:

  • 靜態(tài)不變的,可以成為軟件結構的一篇分
  • 多個變化頻率的,可以封裝成幾個類

此外,參數列表中經常會出現標記參數,這是參數列表變長的另一個重要原因。對于這種標記參數,一種解決方案就是根據這些標記參數,將方法拆分成多個方法。

減少參數列表,越少越好。

到此這篇關于Java雜談之重復代碼是什么的文章就介紹到這了,更多相關Java 重復代碼內容請搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關文章希望大家以后多多支持腳本之家!

相關文章

  • Java實現時間動態(tài)顯示方法匯總

    Java實現時間動態(tài)顯示方法匯總

    這篇文章主要介紹了Java實現時間動態(tài)顯示方法匯總,很實用的功能,需要的朋友可以參考下
    2014-08-08
  • SpringBoot根據各地區(qū)時間設置接口有效時間的實現方式

    SpringBoot根據各地區(qū)時間設置接口有效時間的實現方式

    這篇文章給大家介紹了SpringBoot根據各地區(qū)時間設置接口有效時間的實現方式,文中通過代碼示例給大家講解的非常詳細,對大家的學習或工作有一定的幫助,需要的朋友可以參考下
    2024-01-01
  • Java中獲取類路徑classpath的簡單方法(推薦)

    Java中獲取類路徑classpath的簡單方法(推薦)

    下面小編就為大家?guī)硪黄狫ava中獲取類路徑classpath的簡單方法(推薦)。小編覺得挺不錯的,現在就分享給大家,也給大家做個參考。一起跟隨小編過來看看吧
    2016-09-09
  • 簡單易用的Spring?Boot郵件發(fā)送demo

    簡單易用的Spring?Boot郵件發(fā)送demo

    本文將介紹如何使用Spring?Boot發(fā)送郵件,我們將演示如何配置SMTP郵件服務器,創(chuàng)建一個郵件模板,以及如何使用JavaMailSender發(fā)送郵件,我們還將介紹如何測試我們的郵件發(fā)送代碼
    2023-12-12
  • Java線程安全的計數器簡單實現代碼示例

    Java線程安全的計數器簡單實現代碼示例

    這篇文章主要介紹了Java線程安全的計數器簡單實現代碼示例,具有一定參考價值,需要的朋友可以了解下。
    2017-10-10
  • 分布式系統(tǒng)中的降級熔斷設計問題面試

    分布式系統(tǒng)中的降級熔斷設計問題面試

    這篇文章主要為大家介紹了分布式系統(tǒng)中的降級熔斷設計問題面試解答,有需要的朋友可以借鑒參考下,希望能有所幫助,祝大家多多進步,早日升職加薪
    2022-03-03
  • 解決@RequestBody接收json對象報錯415的問題

    解決@RequestBody接收json對象報錯415的問題

    這篇文章主要介紹了解決@RequestBody接收json對象報錯415的問題,具有很好的參考價值,希望對大家有所幫助。如有錯誤或未考慮完全的地方,望不吝賜教
    2021-06-06
  • 詳解微信開發(fā)之access_token之坑

    詳解微信開發(fā)之access_token之坑

    access_token分類一是普通access_token,二是網頁授權access_token。這篇文章主要介紹了詳解微信開發(fā)之access_token之坑,具有一定的參考價值,感興趣的小伙伴們可以參考一下
    2018-10-10
  • Java基于Socket實現多人聊天室

    Java基于Socket實現多人聊天室

    這篇文章主要為大家詳細介紹了Java基于Socket實現多人聊天室,文中示例代碼介紹的非常詳細,具有一定的參考價值,感興趣的小伙伴們可以參考一下
    2022-09-09
  • SpringBoot配置mybatis駝峰命名規(guī)則自動轉換的實現

    SpringBoot配置mybatis駝峰命名規(guī)則自動轉換的實現

    這篇文章主要介紹了SpringBoot配置mybatis駝峰命名規(guī)則自動轉換的實現,文中通過示例代碼介紹的非常詳細,對大家的學習或者工作具有一定的參考學習價值,需要的朋友們下面隨著小編來一起學習學習吧
    2020-09-09

最新評論