日日操夜夜添-日日操影院-日日草夜夜操-日日干干-精品一区二区三区波多野结衣-精品一区二区三区高清免费不卡

公告:魔扣目錄網為廣大站長提供免費收錄網站服務,提交前請做好本站友鏈:【 網站目錄:http://www.ylptlb.cn 】, 免友鏈快審服務(50元/站),

點擊這里在線咨詢客服
新站提交
  • 網站:51998
  • 待審:31
  • 小程序:12
  • 文章:1030137
  • 會員:747

 

來自亞馬遜的高級工程師 James Hood 以簡單明了的例子說明了為什么要用 DDD 替代 CRUD 來設計 REST API。他提到“DDD 與 REST API 近乎天然地合拍,因為 REST 的資源可以很好地與 DDD 的實體映射起來”。

REST 以資源為中心,這些資源以 URI 的形式呈現。在調用 HTTP 時,通過指定一個 HTTP 動詞和一個資源 URI 對某個特定的資源進行操作。大部分 REST 框架都提供了生成器,你只要指定一個資源的名字,框架就會為你生成腳手架(scaffold)。

不過,這些生成器默認使用的是 CRUD 模型(Create、Read、Update、Delete),它們把資源看成是一系列屬性的集合,使用 JSON 或與特定語言相關的數據對象來表示資源,并生成用于對資源進行創建、讀取、更新和刪除操作的方法。

雖然這給開發者帶來了便利,但我覺得這樣是有問題的。我不喜歡 CRUD 這樣的說法,尤其不喜歡當中的 U

問題:CRUD 中的 U

一般的更新操作允許客戶端更新資源的任何一個字段,并使用新版本覆蓋已有的版本。但如果你允許客戶端這么做,那么你的服務 API 就失去了應有的價值。

服務層的一個關鍵價值在于為底層的數據增加業務約束,因此,資源最終都需要帶上業務約束。

那么,難道我們就不能給更新操作增加業務約束嗎?讓我們以最簡單的銀行賬戶為例。首先,不能讓客戶通過調用 API 來隨意更新他們的賬戶余額。另外,賬戶或許需要最小余額的限制。

你在更新操作里做了一些檢查,賬戶余額的變動必須發生在一個指定的范圍內。那么這樣問題就解決了嗎?當然沒有。任何一次余額的調整都需要與某種事務相對應,不是嗎?是存入、取出,還是轉賬?如果客戶要更改賬戶該怎么辦?這樣做是被允許的嗎?這樣做會不會破壞與其他數據之間的關系?

不難看出,你的更新操作很快會讓這一切變得像意大利面條一樣混亂不堪。我曾經看著一些團隊走上了這條不歸路,他們試圖從更新的字段里去推測客戶的意圖,結果代碼變得像團亂麻。

解決方法:DDD

那么該如何解決這個問題,有其他更好的方案嗎?我個人更喜歡基于領域驅動設計(DDD)來設計 API。DDD 的基本思想是說,軟件的建模應該發生在真實世界的問題得到解決之后。

DDD 使用實體(Entity)和聚合(Aggregate)來描述業務對象,還定義了服務(Service)、值對象(Value Object)和倉庫(Repository)等術語,用以解決業務領域或 DDD 邊界上下文問題。

DDD 不一定非要與 REST 綁定在一起,不過我發現 DDD 與 REST API 近乎天然地合拍,因為 REST 的資源可以很好地與 DDD 的實體映射起來

那么這意味著什么呢?這意味著,你的 API 應該要以 領域對象 以及這些對象所提供的 業務操作為中心。業務操作是對常規更新操作最好的替代品。我們繼續以之前的銀行賬戶為例。

對于銀行的 API 來說,賬戶就是一個領域對象(DDD 里的實體)。這次我們不再使用 CRUD 來為賬戶建模,而是為賬戶定義一組業務操作。以下是一系列寫入操作:

  • 開戶(Open)——新開一個賬戶。
  • 銷戶(Close)——注銷一個已有的賬戶。
  • 取出(Debit)——從賬戶里扣掉一些錢。
  • 存入(Credit)——往賬戶里存入一些錢。

這些操作都帶有一定的 業務約束。例如,往一個已經注銷的賬戶里存錢是不被允許的,而在取錢的時候要強制檢查最小余額。至于讀取操作,我們可以為客戶提供一些有用的查詢:

  • 加載——通過賬戶 ID 加載相應的賬戶信息。
  • 交易歷史——列出賬戶的交易歷史。
  • 客戶的賬戶列表——列出指定客戶的所有賬戶。

在定義好業務操作之后,就可以將它們與 REST API 映射起來:

  • POST /account ——新開一個賬戶。
  • PUT /account//close ——注銷一個已有的賬戶。
  • PUT /account//debit ——從賬戶里扣掉一些錢。
  • PUT /account//credit ——往賬戶里存入一些錢。
  • GET /account/——通過賬戶 ID 加載相應的賬戶信息。
  • GET /account//transactions ——列出賬戶的交易歷史。
  • GET /accounts/query/customerId/——列出指定客戶的所有賬戶。

這些看起來與一般的 CRUD API 非常不一樣,關鍵在于這些操作具有良好的定義。不管對于 服務提供方 還是 客戶端 來說,這樣的體驗都更好。

服務提供方不再需要根據更新字段來推測業務操作的意圖,業務操作清晰明了,這樣的代碼更簡單,也更容易維護。

而對于客戶端來說,它們能執行或不能執行哪些操作也是一目了然的。如果 API 具有良好的文檔化,比如使用了 Swagger,那么就可以很清楚地了解到 API 都具有哪些約束。

定義這樣的 API 需要做一些前期思考,這不同于使用簡單的 CRUD 生成器。如果你打算將 API 暴露成公共端點,就需要在很長的一段時間內為 API 提供支持,最好還是把它看成是一個永久性的事項。

我總是建議人們在前期多花一點時間,因為有些東西到了后面就很難修改,而 API 就是一個很好的例子。

所以,在進行 API(REST 或其他)設計時,請停止使用 CRUD 模型。相反,可以通過 DDD 來定義 API,包括領域對象和它們的業務操作。

如果你想看到更多關于領域對象的例子,可以參考 Amazon Web Services 的 API。在 AWS API 開發者指南里,每一個服務都有對應的“關鍵概念”一節,用以描述領域對象。

例如,S3 里定義了 Bucket、Object 和 Permission 等領域對象,Kinesis 里定義了流(stream)和分片(shard)。先了解一個服務的領域對象,再查看 API 參考,然后瀏覽服務的 API 清單。你會發現,基于這些領域對象構建的 API 在理解和使用上都更加直觀。

英文原文傳送:

http://jlhood.com/there-is-no-u-in-crud/

分享到:
標簽:API
用戶無頭像

網友整理

注冊時間:

網站:5 個   小程序:0 個  文章:12 篇

  • 51998

    網站

  • 12

    小程序

  • 1030137

    文章

  • 747

    會員

趕快注冊賬號,推廣您的網站吧!
最新入駐小程序

數獨大挑戰2018-06-03

數獨一種數學游戲,玩家需要根據9

答題星2018-06-03

您可以通過答題星輕松地創建試卷

全階人生考試2018-06-03

各種考試題,題庫,初中,高中,大學四六

運動步數有氧達人2018-06-03

記錄運動步數,積累氧氣值。還可偷

每日養生app2018-06-03

每日養生,天天健康

體育訓練成績評定2018-06-03

通用課目體育訓練成績評定