如何優雅的解決前後端資料結構不一致的問題?

時間 2021-05-06 22:08:33

1樓:渣渣七

系統上來看,多一環transform ,會增加系統複雜度。那就需要保證transform 足夠穩定的同時,還要在腦海裡時刻做一層轉換以便於排查問題的時候也能對映上。實為下策。

2樓:owen

我們方案是全端都使用grpc,資料結構用idl的protobuf。。。。 對的,沒聽過,前端也用grpc,庫為grpc_web

3樓:熊傑

連刷到好幾下。 本來不想答的, 因為我感覺題主的目的是問怎麼做這個資料轉換的東西。

我的觀點是, 沒必要做這個。 設計資料結構, 處理資料本身就是乙個開發工程師的基本功。 而且我感覺在這上面好像沒有想像力發揮的地方。

4樓:

除了大神們提到的 GraphQL,TypeScript 也是乙個優雅的解決方案。

backend data(JSON) → client typed data(TypeScript) → consume(TypeScript) → to backend(JSON)

這樣一來前端就可以和後端保持基本嚴格一致,包括資料結構和資料型別。

首先不建議使用 lodash,因為在運算過程中會丟失 type。例如使用 get 獲取乙個 object 裡面 deep key,可能會丟失此 type。乙個解決方案就是可以試試 idx。

TypeScript 解決方案最繁瑣最重要的地方在於怎樣將後端來的資料全部對映上相對應的變數型別。這就需要首先和後端溝通好資料結構和型別。

其次在後端返回的資料中有很多是可選的並且沒有預設值。如果乙個 object 是可選的,那獲取裡面的所有 key 的 value 又會有麻煩。所以需要比較好的去定義 type 以及一些泛型(generic)。

這樣的操作一旦層級多了就會變得非常複雜,比較難讀懂。

5樓:HylaruCoder

前端狀態和後端領域模型的抽象方式不一致是乙個逃不了的複雜度

個人觀點是這個過程可以通過前後端都很熟悉的人進行約定, 減少不一致性.

建議定期覆盤, 改善前後端的介面約定來解決問題.

6樓:拼音

你的例子好像有問題,但只是把乙個key對映到另乙個key的這種做起來不難。

只要resolver的每個子函式對獨特輸入有獨特的輸出,你的函式就可以表示為一系列可逆函式的組合也是可逆函式,也就自然完備了。

具體來說mapWith生成的函式明顯是可逆的,再檢查下傳進來的引數裡setIn/getIn有沒有漏下原資料哪個屬性,就能知道resolver是不是可逆的了。

7樓:

我以前公司是這麼處理的。

每個人負責乙個模組。前後端都是他自己做。

在人員變動不頻繁的情況下,可以保證每個模組的一致性。

同時會寫文件,保證接手的同事可以快速跟進。

後來我是這麼處理的。

由於人員技術不夠,不得不前後端分離開發。

但是要求一切以後端為準。後端會進行乙個資料結構判定。

結構不對或者數值預設,就丟擲異常。

如果換我接手乙個前後端不一致的情況。估計會選擇本地建立乙個資料庫進行匹配。

8樓:零式改

我的思路是反過來的。預設當他們是一致,差異較大再轉,並且展現和提交分開思考。

我這裡簡單定義一下,B我們叫它領域模型domian,A我們叫它展現模型viewmodel。

查詢/展現時將領域模型轉為展現模型,這是理想化的情況,而實戰中因為工作量工期等原因,並不是所有都一定要轉,可以把領域模型直接當展現模型。

資料模型—》領域模型—》展現模型

提交時並不是一定要把整個展現模型原封不動提交回去,實際上只提交僅僅用到的最小部分,或許只有乙個引數。

引數—》領域模型—〉運算元據庫

基本上提交時我是避開展現模型的,因為它叫展現模型,也就是說展現用的。

思考一下:

如果,你嘗試將前後端從物理上分離,那麼你想一下領域模型轉展現模型的工作是放在前端好呢?還是後端好呢?

如果放後端,那麼領域模型這一層依賴展現層那還叫領域模型層嗎?顯然放在後端做也不是不可以,只是要在領域模型外加一層來處理這事。這時,展現模型同時貫穿前後端傳輸資料,也可以叫它資料傳輸物件dto。

如果應該放在前端做,那麼後端就不關心如何展現,只提供領域模型,這時領域模型成為了資料傳輸物件。那麼在提交時,不是按照展現模型,而是按照領域模型來的。

所以按照這個思路,你用的是前者,我慣用的是後者。顯然後者不存在你說的這個問題。

9樓:於江水

數學上驗證完備性可能有點複雜,可能需要定義乙個雙向對應關係配置。

我之前也想過類似的問題,思路大概是下面這樣的,簡單分享下,拋磚引玉。後來覺得實現成本也有一些也挺麻煩的,還不如硬編碼來的快就擱置了。除了單純轉換字段結構之外,還可以加一層校驗方便在執行時判斷是哪方的資料結構有問題然後報錯。

首先需要定義字段結構模板描述,比如 API response 的:

之後定義關係,也是可以自己隨便定的:

A['data']['aaa'] = B['aaa'];

A['data']['bbb']['bbc'] = B['ccc'];

之後拿到了 A 先進行校驗格式,然後解析定義的關係開始生成 B,判斷 B 有乙個 ccc 然後值是 A['data']['bbb']['bbc'] 那麼就用類似 lodash get 之類的方法去獲取這樣。反過來也是一樣的,如果是多層結構,那麼判斷 object 不存在的時候,就可以先建立乙個 key 再繼續下去。然後既然定義了模板,也可以再加乙個無用資料清洗的功能,把多餘的資料去掉(這塊可以參考 RoR 的 params 的校驗和清洗功能:

What is `params.require(:person).

permit(:name, :age)` doing in Rails 4?

當然肉眼也能看到這套方案簡直太複雜了,如果字段很多,雙向關係定義也很多,然後欄位變了還需要維護更多東西(雖然執行時欄位校驗這個功能挺實用的,GraphQL 就提供了,真香)。同時可能實際場景並沒有這麼多地方要用到這種東西,除了一些特定領域之外,常見的功能基本用不到這個,因為本身 response 和 request 就是不一樣的,比如乙個購物車,API 的 response 是產品列表和分類,前端 request 時 post 的資料是購物車資料的定義,而且是另乙個介面,所以就沒有題主這個問題了。

所以最簡單直接的還是設計乙個統一的模型,加乙個轉換層。然後就看前後端誰比較強勢了,誰強就把這個轉換層放在對方那邊。不過通常來說放在後端比較合適,定義好標準的模型,這樣多個端不需要各自去實現一遍,控制起來也好控制,底層儲存模型或者其他子系統的格式變了,無需發布客戶端,後端再加一層就可以解決。

有朋友提到 GraphQL,GraphQL 解決不了題主的問題,它可以重新命名字段,只獲取部分字段,但本身的結構還是在哪的,目前沒有提供調整結構對映的功能。

java如何優雅使用棧這個資料結構?

聖魯安德斯 LinkedList 既有棧的 pop,push 方法,又有佇列的 offer,poll 方法,還有deque的 addfirst,addLast,removeFirst,removeLast 方法,還有collection 都有的 add,remove 方法,還有棧和堆的 peek 方...

如何設計出精巧的資料結構?

雲悠水澈 這個問題,並不是一篇文章或一本書就能說清楚的,需要對特定問題深入的分析和大量的練習,建議多看一些成熟的協議,這些協議中的資料結構基本都很精巧,總結吸收裡面面對問題的設計思想和技巧。核心是 簡練 清楚明白。比如 iCalendar RFC 5545中怎樣準確標識乙個事務,怎樣處理乙個事務的迴...

資料結構的基本演算法如何學得紮實,做題寫專案游刃有餘。

AmberGarden 資料結構主要分為如何定義資料結構裡面的資料和如何運算元據 把自己的主要精力放在這兩部分 資料部分。為什麼在這個資料結構裡面有這些資料,它裡面記錄了什麼資訊,這些資訊的修改規則是什麼,和其它資料是否有關聯?操作部分。每個操作是要達成什麼目標?這個目標達成以後資料是什麼樣的?我們...