2010-10-05 66 views
63

我目前正在爲現有的PHP應用程序設計API,爲此我正在研究REST作爲一種明智的架構方法。我應該如何處理RESTful API中的對象層次結構?

我相信我對關鍵概念有一個合理的把握,但我正在努力尋找解決了對象層次結構和REST的人。

這裏的問題...

在[應用]業務對象的層次結構,我們有:

Users 
L which have one-to-many Channel objects 
L which have one-to-many Member objects 

在應用程序本身,我們使用延遲加載的方式來填充的陣列的用戶對象這些對象根據需要。我相信OO術語這是對象聚合,但是我看到了各種命名不一致的情況,並且不關心開始一場關於精確命名約定的戰爭。

現在,請考慮我有一些鬆散耦合的對象,根據應用程序的需要,我可能會/可能不會填充這些對象。

從REST的角度來看,我試圖確定該方法應該是什麼。這是我目前的想法(只考慮GET暫時):

選項1 - 完全填充的對象:

GET api.example.com/user/{user_id} 

閱讀用戶對象(資源),並與所有返回的用戶對象預先加載和編碼的可能的Channel和Member對象(JSON或XML)。

優點:減少的對象的數目,沒有對象層次的遍歷需要
缺點:對象必須完全填充(昂貴的)

選項2 - 填充主對象和包括鏈接到其他對象資源:

GET api.example.com/user/{user_id} 

閱讀用戶對象(資源),並返回填充用戶對象的用戶數據和兩個列表。

每個列表引用相應(子)資源即

api.example.com/channel/{channel_id} 
api.example.com/member/{member_id} 

我認爲這是接近(或精確地)超媒體的影響 - 只要客戶能得到其他資源,如果它想(我明智地標記他們)。

優點:客戶可以選擇加載下屬或以其他方式,如REST資源的對象的更好的分離
缺點:獲得二次資源

方案3需要進一步的行程 - 使遞歸檢索

GET api.example.com/user/{user_id} 

閱讀用戶對象幷包含指向子對象列表的鏈接即

api.example.com/user/{user_id}/channels 
api.example.com/user/{user_id}/members 

的/頻道呼叫將在形式返回信道資源的列表(如上):

api.example.com/channel/{channel_id} 

優點:第一資源暴露到哪裏得到subodinates但他們不是什麼(更多RESTful?),不需要預先獲得下屬,下屬列表生成器(/通道和/成員)提供接口(方法)使響應更像服務。
缺點:現在需要充分填充物三個電話

選項4 - (重新)考慮REST

我重新使用[現行]應用對象的層次結構,並試圖對象設計將其應用於REST - 或者可能更直接地爲其提供API接口。

也許REST對象層次結構應該是不同的,或者新的RESTful思想可能會暴露現有對象設計的侷限性。

對上述任何想法都表示歡迎。

非常感謝

保羅

+0

在我搜索我也發現了這組文章,我發現非常有用的和可訪問:http://www.infoq.com/minibooks/emag-03-2010-rest – paulkmoore 2010-10-06 10:18:38

+0

如果你正在尋找一個所有這些樣式基於JSON的媒體類型,考慮商事:http://www.aminus.org/rbre/shoji/shoji-draft-02.txt – fumanchu 2010-10-06 17:45:46

回答

38

沒有理由不將這些。

  • api.example.com/user/{user_id} - 返回用戶表示
  • api.example.com/channel/{channel_id} - 返回信道表示
  • api.example.com/user/{user_id}/channels - 返回通道表示的
  • api.example.com/user/{user_id}/channel_list列表 - 返回通道ID列表(或鏈接到他們的充分陳述,使用上述鏈接)

如果有疑問,考慮如何將數據顯示給用戶沒有「API」問題:用戶需要索引頁({user_id}/channel_list)和完整視圖({user_id}/channels)。

一旦你有了這些,只需要支持JSON而不是HTML(作爲表現形式),並且你有REST。

+1

偉大的方式把它。 – 2010-10-05 20:41:15

+0

皮埃特 - 非常感謝,這是非常有用的。我想澄清從人的角度來看穿過數據的觀點。我的想法是,如果我提供的「下一個」資源列表,而不是一個「完全視圖」我允許用戶細讀他們想要細讀什麼,因此提供的鏈接列表是「多」的RESTful(以HATEOS符合較好)。我可以理解,提供填充列表對於性能原因很有用。我知道這是有點用例相關的,但我不知道我會更好地保持接口簡單(也許更慢)暫且? – paulkmoore 2010-10-06 10:14:06

+3

你如何創建這樣的分層對象?例如假設我們有圖書館 - >書籍 - >章節 - >頁面。現在有一種方法是創建一個龐大的庫對象,但有什麼選擇?如果您先創建圖書館,先獲取該圖書,然後預訂等。 – 2012-06-20 03:26:27

24

我可以給出的最好建議是儘量避免將REST API視爲暴露對象。您創建的資源應該支持您需要的用例。如果必要的話,你可能會爲所有三個選項創建資源:顯然

api.example.com/completeuser/{id} 
api.example.com/linkeduser/{id} 
api.example.com/lightweightuser/{id} 

我的名字是有點愚蠢,但它其實並不重要,你叫他們什麼。這個想法是,您可以使用REST API來以特定使用場景的最合理的方式呈現數據。如果有多個場景,請根據需要創建多個資源。我喜歡將我的資源更像UI模型而不是商業實體。

+0

達雷爾 - 感謝這 - 也非常有用。我懷疑我錯過了對象映射周圍的一些細微之處。我得出結論,雖然我可能會調用我現有的對象框架,但我需要仔細設計我的'資源視圖'。謝謝。 – paulkmoore 2010-10-06 10:16:29

6

下面是幾個小時我的結論搜索,並從這裏開始應答輸入:

在那裏我有一個對象,它實際上是一個多部分對象,我需要把它看成一個單一的資源。因此,如果我獲得對象,所有的子座標都應該存在。這是必需的,以便資源可以緩存。如果我分開加載對象(並提供一個ETag圖章),那麼其他請求者可能會收到一個部分對象,當他們期望一個完整的對象時。 結束語 - 如果對象作爲資源可用,則應完全填充對象。

相關對象關係應作爲指向其他(主要)資源的鏈接。通過這種方式,可以通過遍歷API來發現對象

另外,對於主應用程序站點而言有意義的對象層次結構可能不是您需要以RESTful方式執行的操作,而是更有可能揭示現有層次結構的問題。說了這些之後,API可能需要比以前設想更多的專用用例,並且可能需要專門的資源。

希望幫助別人

9

我會建議Restful Obects這是標準的暴露域模型的寧靜

寧靜的對象的想法是提供一個標準的,通用的RESTful接口的域對象模型,露出的表示其結構使用JSON並使用HTTP GET,POST,PUT和DELETE啓用與域對象實例的交互。

根據標準,這些URI將是這樣的:

  • api.example.com/object/user/31
  • api.example.com/object/user/31/properties/username
  • api.example.com/object/user/31/collections/channels
  • api.example.com/object/user/31/collections/members
  • api.example.com/object/user/31/actions/someFunction
  • api.example.com/object/user/31/actions/someFunction/invoke

還有其他資源

  • api.example.com/services
  • api.example。COM /域類型

該規範定義了幾個主要表示:

  • 對象(其表示任何域對象或服務)
  • 列表(鏈接到其他對象)
  • 屬性
  • 收集
  • 行動
  • 作用的結果(通常CONTA進不去爲對象或列表,或者只是反饋消息)
  • ,也有少數次要的表示,如家,和用戶

這是有趣的,因爲你會看到,表示是完全的自我描述,如果需要,開放普通觀衆的可能性。

可替代地,所述表示可以直接由一個定製應用消耗。

相關問題