你的代碼中的技術(shù)細(xì)節(jié)和業(yè)務(wù)邏輯分開了么?

什么是技術(shù)細(xì)節(jié),業(yè)務(wù)邏輯?

業(yè)務(wù)人員和開發(fā)人員對(duì)需求的時(shí),常常會(huì)出現(xiàn)下面這段對(duì)話。

業(yè)務(wù)人員:我希望加一個(gè)用戶注冊(cè)的功能,用戶要填入自己的用戶電話,郵箱,還有頭像,我們保存圖片需要進(jìn)行大小縮放,以便符合我們的要求,同時(shí)電話,郵箱要有效。
開發(fā)人員1:好的,當(dāng)用戶注冊(cè)的時(shí)候,需要前端檢查電話號(hào)碼,郵箱是否正確。然后獲得頭像圖片,進(jìn)行圖片處理,最后存到MySQL中的user和account表中。

用戶注冊(cè)操作代碼實(shí)現(xiàn)如下

class UserService {
  public void createUser(String username, String avatar,  String phone, String email, String password){
      if(password == null){
        return;
      }
      if(password.contains("*")){
        return;
      }
      ...
      String uploadUrl = getPicture(avatar)
      User user = new User(username, phone, email, uploadedUrl);
      userRepo.save(user);
  }
  private void getPicture(String avatar){
      File avatarFile = processPicture(avatar)
      // uploadFile 實(shí)現(xiàn)邏輯
    ...
  }
 // 圖片處理,使得圖片大小在一個(gè)規(guī)定的值
  private File processPicture(String avatar){
    //下載圖片
    //判斷圖片大小是否符合標(biāo)準(zhǔn)
    //當(dāng)圖片過大,進(jìn)行圖片裁剪
    //當(dāng)圖片過小,進(jìn)行圖片放大
    ...
  }
}
class User{
  private String username;
  private String phone;
  private String email;
  private String uploadedUrl;
  private String avatar;
}

可以看到,上面的對(duì)話和代碼實(shí)現(xiàn),包含2類內(nèi)容。技術(shù)細(xì)節(jié)和業(yè)務(wù)邏輯。

  • 技術(shù)細(xì)節(jié):它們和業(yè)務(wù)無關(guān),僅僅代表應(yīng)用中的一種技術(shù)能力。如,我的數(shù)據(jù)庫(kù)表如何設(shè)計(jì),驗(yàn)證誰(shuí)來做,是前后端分離還是不分離,數(shù)據(jù)是從前端來,還是從后端給。
  • 業(yè)務(wù)邏輯:它們和業(yè)務(wù)相關(guān),代表應(yīng)用中的一種業(yè)務(wù)能力。如,填入電話,郵箱,頭像圖片,圖片大小的規(guī)定。

再看看UserService,主要實(shí)現(xiàn)注冊(cè)功能的類。processPicture方法中存在了處理圖片的邏輯(裁剪圖片,放大圖片等技術(shù)細(xì)節(jié)),也包含了業(yè)務(wù)邏輯(規(guī)定的圖片大?。?。當(dāng)我們想從UserService中了解業(yè)務(wù)邏輯時(shí),我們需要讀懂processPicture方法。我們需要花很長(zhǎng)的時(shí)間去理解processPicture方法中的技術(shù)細(xì)節(jié)是在做什么(如何做圖片裁剪,如何做放大圖片操作)。然而,過多的技術(shù)細(xì)節(jié)展現(xiàn)對(duì)于了解業(yè)務(wù)邏輯沒有任何幫助,反而會(huì)使人凌亂。使得代碼不那么清晰。

用戶注冊(cè)操作代碼修改

class UserService {
  private int WIDTH_PIXEL = 1024;
  private int HIGHT_PIXEL = 1024;

  public void createUser(String username, String avatar,  String phone, String email, String password){
      if(password == null){
        return;
      }
      if(password.contains("*")){
        return;
      }
      ...
      String uploadedUrl = FileUtils.processPictureTo(avatar, WIDTH_PIXEL, HIGHT_PIXEL)
      User user = new User(username, phone, email, uploadedUrl);
      userRepo.save(user);
  }
}

class User{
  private String username;
  private String phone;
  private String email;
  private String uploadedUrl;
  private String avatar;
}
class FileUtil {
  public String processPictureTo(String avatar,WIDTH_PIXEL, HIGHT_PIXEL){
    //下載圖片
    //判斷圖片大小是否符合標(biāo)準(zhǔn)
    //當(dāng)圖片過大,進(jìn)行圖片裁剪
    //當(dāng)圖片過小,進(jìn)行圖片放大
    //上傳圖片
  }
}

再看修改后,我們將技術(shù)細(xì)節(jié)封裝到了個(gè)新的類FileUtil中,同時(shí)將圖片縮放的大小這個(gè)業(yè)務(wù)邏輯放在UserService中。這樣,我們?cè)谧xUserService的時(shí)候,就可以更清晰的了解業(yè)務(wù)邏輯。

為什么要區(qū)分?

大腦的短期記憶無法一次容納約7個(gè)以上的記憶項(xiàng)目 —— 《金字塔原理》

當(dāng)一個(gè)開發(fā)人員去熟悉一個(gè)新模塊的時(shí)候,首先會(huì)從整體去了解這個(gè)新模塊提供的功能,然后再會(huì)去看每個(gè)功能具體的實(shí)現(xiàn)細(xì)節(jié)是什么。就像畫畫一樣,一開始要畫草圖去確定各個(gè)部分畫什么東西,然后再慢慢補(bǔ)充細(xì)節(jié)。所謂細(xì)節(jié)都是魔鬼,如果一開始就進(jìn)入細(xì)節(jié),就容易陷入到細(xì)節(jié)中去,很難看到全局并找到重點(diǎn)。
因此,從認(rèn)知的角度,我們其實(shí)一開始關(guān)注的是業(yè)務(wù)邏輯,當(dāng)了解到我們關(guān)心的業(yè)務(wù)邏輯后,才會(huì)去做技術(shù)細(xì)節(jié)的展開。因此,我們可以把業(yè)務(wù)邏輯的代碼和具體的技術(shù)實(shí)現(xiàn)進(jìn)行分離,這樣,可以幫助我們通過整體-細(xì)節(jié)的方式進(jìn)行學(xué)習(xí)。

如何區(qū)分業(yè)務(wù)邏輯和技術(shù)細(xì)節(jié)?

我們可以通過問問題的方式來區(qū)分現(xiàn)在做的這個(gè)事兒是業(yè)務(wù)邏輯還是技術(shù)細(xì)節(jié)。

  • 這個(gè)事兒業(yè)務(wù)人員關(guān)心么?有業(yè)務(wù)價(jià)值么?
    排序算法業(yè)務(wù)關(guān)心么?把數(shù)據(jù)存到關(guān)系型數(shù)據(jù)庫(kù)還是文檔型數(shù)據(jù)庫(kù)業(yè)務(wù)關(guān)心么?實(shí)時(shí)計(jì)算結(jié)果還是提前計(jì)算好結(jié)果保存下來,業(yè)務(wù)關(guān)心么?是先取A數(shù)據(jù)進(jìn)行計(jì)算還是先去B數(shù)據(jù)計(jì)算,業(yè)務(wù)關(guān)心么?有價(jià)值么?
    如果答案是:Yes,那么這就是業(yè)務(wù)邏輯,如果答案是:No,那么這些可能就是技術(shù)細(xì)節(jié),需要封裝到別處去
  • 這個(gè)事兒換一種方式可以達(dá)成么?
    冒泡排序可以換成其他方式?MySQL存儲(chǔ)換一種方式可以達(dá)成么?實(shí)時(shí)計(jì)算結(jié)果換一種方式能達(dá)成么?
    如果答案是:Yes,那么這就是技術(shù)細(xì)節(jié),如果答案是:No,那么就是業(yè)務(wù)邏輯

區(qū)分后該怎么辦?

分清了業(yè)務(wù)邏輯和技術(shù)細(xì)節(jié)后,我們需要把他們進(jìn)行分區(qū)。
將業(yè)務(wù)邏輯放到一個(gè)package中,將技術(shù)細(xì)節(jié)放到一個(gè)package中。

三層架構(gòu)

業(yè)務(wù)邏輯集中在service層中。業(yè)務(wù)無關(guān)的技術(shù)細(xì)節(jié)按照功能放到其他層。

- Controller
  - TaskRequest
  - TaskController
  - TaskCreateRequest
  - ProjectController
  - ProjectResponse/ProjectVO
- Service
  - Task
    - TaskService
    - Task
  - Project
    - ProjectService
    - Project
  - Picture
    - Picture
    - PictureService
- Repository
- Utils
  - EdocUtils
  - PicutreUtils
- Config
  - LogConfig
  - HealthCheckConfig

六邊形架構(gòu)

- adapter
  - inbound(外部對(duì)本服務(wù)的訪問,UI,controller)
    - rest
      - resources
        - TaskRequest
    - rpc
  - outbound(本服務(wù)訪問三方系統(tǒng),db,中間件,服務(wù))
    - persist
- application(用例,用例可以調(diào)用多個(gè)domain里面的service)
  - usecase 
    - TaskUseCase
    - ProjectUseCase
- domain(業(yè)務(wù)模型)
  - task
    - Task
    - TaskRepo
  - project
    - Project
    - ProjectService
- config(配置信息)
  - LogConfig
  - HealthCheckConfig
最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
【社區(qū)內(nèi)容提示】社區(qū)部分內(nèi)容疑似由AI輔助生成,瀏覽時(shí)請(qǐng)結(jié)合常識(shí)與多方信息審慎甄別。
平臺(tái)聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點(diǎn),簡(jiǎn)書系信息發(fā)布平臺(tái),僅提供信息存儲(chǔ)服務(wù)。

相關(guān)閱讀更多精彩內(nèi)容

  • 一、生命周期 一個(gè)事物一旦出生,就必然會(huì)長(zhǎng)大,變異,一旦長(zhǎng)大,就面臨著衰老,接下來就是消亡了,這個(gè)過程就稱為一個(gè)事...
    ZyBlog閱讀 2,858評(píng)論 1 11
  • 最近與幾個(gè)朋友聊天,不知不覺的,大家都聊到了壓力巨大。不知道什么時(shí)候,壓力成了當(dāng)代年輕人的代名詞:生活中買不起房,...
    翹課叔叔好閱讀 280評(píng)論 2 4
  • 簡(jiǎn)介 2019年新學(xué)期起,決定開始Leetcode刷題,并在博客總結(jié)記錄。 內(nèi)容 292 Nim游戲這其實(shí)是一個(gè)B...
    Zack_H閱讀 500評(píng)論 0 0
  • “我總覺得自己還是個(gè)十三歲的少年,不知道怎樣做一個(gè)大人。就好像我在假裝過自己的人生,做著筆記,等以后真的長(zhǎng)大的時(shí)候...
    周洲的日常閱讀 368評(píng)論 0 0
  • 朝思娘, 晚思娘。 昨夢(mèng)依稀又下房, ...
    宛禾的園子閱讀 649評(píng)論 6 6

友情鏈接更多精彩內(nèi)容