开发过程中,在三个Model的REST描述上,我昨天冥思苦想了一整天。突然对REST有了顿悟,对于以前的错误理解捶胸顿足。
[b]REST不是什么?[/b]
1. REST不是技术
之所以说REST更接近道,是因为REST不是一种技术,而是一种思想,任何方式都可以实现。使用Rails 1.2不代表使用了REST。
2. REST不是Model的Proxy
以为只要Model和Model的关系设计好了,REST风格的URL就被决定了。这就是我前段时间所犯的最愚蠢的错误。这种思想让我用Model First的方式设计系统。结果系统实现得越多,离用户价值越远。
3. REST不是 map.resources,更不是Nested Resource
如果按照Model的层次关系来设计URL,如果层次关系很深,必然导致Nested Resource的层次很深。而是否需要这样的URL应该由需求决定,而不是Model。
[url=http://weblog.jamisbuck.org/2007/2/5/nesting-resources]这篇文章[/url]以及评论讲得非常好。Nested Resource的目的是向URI中加入以及解析必须的参数,而不是把Model的关系展现出来,更不是在URL上耍酷。
至于加入什么参数,完全是由需求决定。
4. REST不是Model的CRUD与Controller的绑定
假如我需要这样两个用户接口:
[code]GET /:project_name/messages[/code]
某一个Project的所有Message
[code]GET /:project_name/tags/:tag_name/messages[/code]
某一个Project的某一个tag的所有Messages
如果一定要按照常见的CRUD原则来作,这两个操作都应该访问Messages Controller的'index' Action,然后判断params里面是否有tag_name参数。这就是我犯过的愚蠢的错误。
[code]class MessagesController < ApplicationController
def index
if params[:tag_name]
@messages = Message.find_by_tag_name_and_project(params[:tag_name], params[:project_name])
else
@messages = Message.find_by_project(params[:project_name])
end
end
end[/code]
正确做法:
[code]map.connect '/:project_name/tags/:tag_name/messages', :controller => 'tag_messages'[/code]
这个URL请求就会分发到TagMessages的 index. 这样作不会引入更多的Controller和Action么?没错!
[code]class MessagesController < ApplicationController
def index
@messages = Message.find_by_project(params[:project_name])
end
end[/code]
[code]class TagMessagesController < ApplicationController
def index
@messages = Message.find_by_tag_name_and_project(params[:tag_name], params[:project_name])
end
end[/code]
既然[code]/:project_name/messages[/code]和[code]/:project_name/tags/:tag_name/messages[/code]是两个不同的用户接口,为什么要放到一个Action里面?多个不同地请求在同一个action里面用if ... else if... 来判断好还是由各自的action执行好?
[b]REST是什么?[/b]
REST体现了软件开发的最终目标:实现用户价值!实现用户价值的开发就要求我们从User Interface开始设计,而不是Model。
无论是BS还是CS架构,对于Server端来说,用户接口就是网络协议,比如HTTP。HTTP接口就是Web Server的User Interface,同时也是Client端的Service Interface。从HTTP接口开始设计Web架构就是REST思想。
HTTP接口是什么?URI,HTTP Method 以及Content-type, Accept-language等HTTP Header的一个集合就是一个HTTP接口。
对于HTTP接口来说,无论是View的代码怎么写,还是Controller和Model怎么实现都属于实现细节。从这点来讲,HTTP接口是系统中最稳定的User Interface。
MVC各个部分的实现也要从User Interface来实现,这些部分的User Interface是什么我还没想好。至少TDD的Test First就是一种User Interface First的体现。
REST与其他思想万法归宗,是一种道。请读者不要把本文当作文字或者概念,更不要对文字产生任何争论。真正的道纯属个人领悟,只要是文字描述出来的就不是道,执著于文字更是愚蠢至极。
[b]REST不是什么?[/b]
1. REST不是技术
之所以说REST更接近道,是因为REST不是一种技术,而是一种思想,任何方式都可以实现。使用Rails 1.2不代表使用了REST。
2. REST不是Model的Proxy
以为只要Model和Model的关系设计好了,REST风格的URL就被决定了。这就是我前段时间所犯的最愚蠢的错误。这种思想让我用Model First的方式设计系统。结果系统实现得越多,离用户价值越远。
3. REST不是 map.resources,更不是Nested Resource
如果按照Model的层次关系来设计URL,如果层次关系很深,必然导致Nested Resource的层次很深。而是否需要这样的URL应该由需求决定,而不是Model。
[url=http://weblog.jamisbuck.org/2007/2/5/nesting-resources]这篇文章[/url]以及评论讲得非常好。Nested Resource的目的是向URI中加入以及解析必须的参数,而不是把Model的关系展现出来,更不是在URL上耍酷。
至于加入什么参数,完全是由需求决定。
4. REST不是Model的CRUD与Controller的绑定
假如我需要这样两个用户接口:
[code]GET /:project_name/messages[/code]
某一个Project的所有Message
[code]GET /:project_name/tags/:tag_name/messages[/code]
某一个Project的某一个tag的所有Messages
如果一定要按照常见的CRUD原则来作,这两个操作都应该访问Messages Controller的'index' Action,然后判断params里面是否有tag_name参数。这就是我犯过的愚蠢的错误。
[code]class MessagesController < ApplicationController
def index
if params[:tag_name]
@messages = Message.find_by_tag_name_and_project(params[:tag_name], params[:project_name])
else
@messages = Message.find_by_project(params[:project_name])
end
end
end[/code]
正确做法:
[code]map.connect '/:project_name/tags/:tag_name/messages', :controller => 'tag_messages'[/code]
这个URL请求就会分发到TagMessages的 index. 这样作不会引入更多的Controller和Action么?没错!
[code]class MessagesController < ApplicationController
def index
@messages = Message.find_by_project(params[:project_name])
end
end[/code]
[code]class TagMessagesController < ApplicationController
def index
@messages = Message.find_by_tag_name_and_project(params[:tag_name], params[:project_name])
end
end[/code]
既然[code]/:project_name/messages[/code]和[code]/:project_name/tags/:tag_name/messages[/code]是两个不同的用户接口,为什么要放到一个Action里面?多个不同地请求在同一个action里面用if ... else if... 来判断好还是由各自的action执行好?
[b]REST是什么?[/b]
REST体现了软件开发的最终目标:实现用户价值!实现用户价值的开发就要求我们从User Interface开始设计,而不是Model。
无论是BS还是CS架构,对于Server端来说,用户接口就是网络协议,比如HTTP。HTTP接口就是Web Server的User Interface,同时也是Client端的Service Interface。从HTTP接口开始设计Web架构就是REST思想。
HTTP接口是什么?URI,HTTP Method 以及Content-type, Accept-language等HTTP Header的一个集合就是一个HTTP接口。
对于HTTP接口来说,无论是View的代码怎么写,还是Controller和Model怎么实现都属于实现细节。从这点来讲,HTTP接口是系统中最稳定的User Interface。
MVC各个部分的实现也要从User Interface来实现,这些部分的User Interface是什么我还没想好。至少TDD的Test First就是一种User Interface First的体现。
REST与其他思想万法归宗,是一种道。请读者不要把本文当作文字或者概念,更不要对文字产生任何争论。真正的道纯属个人领悟,只要是文字描述出来的就不是道,执著于文字更是愚蠢至极。