2011-07-23 81 views
6

我目前在一個新的網站設計版本API的過程。我瞭解如何命名空間的路線,但我堅持在模型中實現版本化方法的最佳方式。API版本

下面的代碼樣品使用Rails框架,但問題的原則應該是大多數Web框架保持一致。

的路線目前看起來是這樣的:

MyApp::Application.routes.draw do 
    namespace :api do 
    namespace :v1 do 
     resources :products, :only => [:index, :show] 
    end 
    end 
end 

而且控制器:

class Api::V1::ProductsController < V1Controller 
    respond_to :json, :xml 

    def index 
    respond_with @products = Product.scoped 
    end 

    def show 
    respond_with @product = Product.find(params[:id]) 
    end 
end 

所以,很顯然,我們只是暴露可在這裏的產品屬性,此解決方案,如果你的偉大工程」只會有一個版本的API。當你想要發佈V2和V2需要重新實現產品名稱的顯示方式時(在保持與V1的向後兼容性的同時 - 至少在短期內),會發生什麼?

據我看到它,你有兩個選擇......爲V1

  1. 拖放支持立即處理的後果(最壞可能的解決方案)
  2. 你開始重寫to_ [格式]的方法(我敢肯定你附上as_ at [格式]做到這一點,但是這是題外話),包括一個新的屬性... name_2 - 這似乎也同樣愚蠢
  3. 執行某種代理類是隻負責曝光我們之後的方法
  4. 個讓視圖來處理建立某種哈希的版本控制器,並呼籲to[format] ...

三,四都是我倒認爲唯一的使得任何形式的感...三個看起來會如:

# model 
class Api::V1::Product < Struct.new(:product) 
    def to_json 
    attributes.to_json 
    end 

    def to_xml 
    attributes.to_xml 
    end 

private 
    def attributes 
    {:name => product.name} # add all the attributes you want to expose 
    end 
end 

# Controller 
class Api::V1::ProductsController < V1Controller 
    respond_to :json, :xml 

    def show 
    respond_with @product = Api::V1::Product.new(Product.find(params[:id])) 
    end 
end 

過去有其他人做過什麼?

回答

6

而是一個應用服務V1和V2和V的......你部署的每個版本的一個應用。一個應用程序將回答api.domain.com/v1,然後另一個應用程序將回答api.domain.com/v2等。

即面向服務的應用程序是如何組織得最好的,每個服務應隔離,獨立的部署。

從單個應用程序提供所有版本都會破壞面向服務設計的目的,因爲每次您在一個服務中進行更改時都需要測試和部署所有服務。

+0

這是一個非常好的解決方案 - 我沒有想到... – Coop

-1

我想你可能是在工程的API,如果你打算創建不同的版本。只要您永遠不會刪除前進的網址和屬性,那麼舊客戶端就可以繼續使用您的API。只要使用v1,v2等作爲隔離客戶端的方法,就可以在API繞開bug或怪癖的時候分離客戶端。

如果您將底層架構改爲原始API可以支持的範圍,那麼我同意您需要爲舊平臺創建代理,如果您計劃支持舊客戶端。對於新系統,我會按照@Nerian的建議創建一個全新的端點服務器。