基于REST方法的产品设计

在我不长不短的产品开发生涯中,我接触到的苦逼的程序员最怕碰到的是不靠谱的产品设计。很多初出道的产品设计由于没有真正接触过开发,也无法理解开发到底是在做什么,经常会画蛇添足地增加不必要的功能,同时却没有把核心功能的方方面面都覆盖到位。

他们最常说的两句话是:

  • “就加一个输入框和一个按钮,这开发成本很大吗?”
  • “啊?这里还有一个页面要设计啊?”

不可能让程序员都转行去做产品。产品需要灵感、想像力,以及品位,而开发需要严谨、周密,以及抽象。

但是一个设计完备,结构精巧的产品,需要两者兼备。

在服装设计行业,设计师不会仅仅在纸上画画图,还会真实地去挑选面料并自己裁剪。而程序设计则远没这么容易,程序开发是人类极为少见的以工程的方式生产出抽象的成果的活动——软件无质无形,其成果都在每个人自己的想象之中。在产品设计阶段如何判断到底有多少东西要做变得困难,要不这世界上也不会有那么多失败的软件项目了。

我有幸做过一段时间产品设计,加上自己业余时间也独立开发过一些项目,发现一个比较有效的方法,分享于此。主要给一些产品设计新手作为参考。

REST

人类发明了计算机,并用二进制的方式将命令发给处理器。先驱和先烈们发现处理器命令都是类似10011100这样的东西,没法记,就发明了汇编。汇编之后产生了程序设计语言和对应的编译器,再后来,人们发现命令式的编程语言仍然难以驾驭现实问题的复杂性,又发明了面向对象的编程语言。无论你认为函数式编程会比面向对象高级几条街,不可否认的是,在大量的项目中,面向对象仍然是首选的编程方式。

面向对象的程序设计大致来说就是将程序中各种角色抽象成一种包含属性和方法的对象。比如一个记账的软件里面,就有金钱这个对象,它至少有数量和单位两个属性,还有支出和收入两种方法。当然还有大量程序内用户难以观察到的对象,如日志(loggin)对象,则至少有日志文件地址这个属性,和打印日志这个方法。

REST则是在更上层,从业务层面来约定设计概念以及准则的思路。为了简化其概念,我在此主要抽出与产品设计相关的一个子集,大概可以这样描述:

网络上所有事物都被抽象为资源,他们通过通用的接口来与彼此及用户交互。

前半句话比较容易理解:比如一个Blog系统,则至少有文章(Artical)和评论(Comment)两种资源;一个电子商务系统,至少有商品(Commodity)、购物车(Cart)、订单(Order)和顾客(Customer)四种资源。

后半句话怎么理解呢?

CURD

CURD是针对一个资源最基本的四种操作:创建(Create),更新(Update),读取(Read)和删除(Destroy)。在实际的应用中,因为用户的参与,还需要在增加三个操作:新建(New),编辑(Edit)和索引(Index)。这七个操作,也就是Rails在引入REST资源概念之后所默认的七种方法。

基本上在产品设计的时候,拿着这七种方法去检查功能的设计,不能保证你能设计出完美的产品(那是你的命运应该负责的事),但至少不会设计出功能缺失的产品。也就是说你那两句常说的话可以少说很多次了。

来看例子。

简单应用

我们把七种方法稍加整理,变成五部分:

  • index
  • show(read)
  • new & create
  • edit & update
  • destroy

以Blog中的Artical为例。

index的意思是索引,也就是如何展示资源的集合。在这里,就是如何展示多篇文章。这就是Blog的列表页,无论你是否要翻页,一页显示5条还是10条,你总不能把这个页面给省掉吧。

show的意思是如何展示单个资源,在大多数blog系统中就是单篇文章的页面。

newcreate描述如何创建一个新的资源,也就是如何创建一篇新的文章。但这其实包含两部分:填写新文章的输入页面,和提交新文章时的反馈。前一部分就是新文章的表单页,而后一部分则需要设计:是给一个成功提示页,还是直接跳转到新文章的展示页(show),又或者是跳到集合页(index)。

editupdate同样,前者是修改文章的编辑页,后者是提交修改后的反馈:成功提示页、跳到文章展示页,又或者是跳到集合页。

destory很简单,提交删除之后,如何返回:提示删除成功,或者跳到集合页(嗯,这时候被删的那条已经不见了)。

以上就是一个Artical所必须的七个页面,当然可以在真实的设计中将其中某些页面做成多次显示,比如Blog系统前台需要显示集合页,后台管理系统中同样会显示文章集合。但是你不能省掉其中某个方法,不然功能就残了。

对于Artical资源,这七种方法当然缺一不可。幸运的是,我在前面说过,这七种方法是用来检查有无缺失的,并不表示对于每种资源都需要完备的七个页面才行。比如对于Comment资源,评论都显示在文章下方,所以只有index页,没有针对单条评论的show页,同时修改和更新也不需要,所以editupdate也不用设计。就剩下indexnewcreatedestory四种方法需要设计——你已经审视过并确认另外三个可以没有了,不用担心自己是否漏掉什么重要的东西了。

抽象应用

如果你已经熟练应用这个方法了,那么可以开始训练自己用这种方法审视抽象资源了。

比如,用户注册(new),修改资源(edit)甚至注销账号(destory)都可以用上面的方法来检查,但是,用户登陆(login)和登出(logout)呢?

这里需要一些抽象思维。在大多数产品的实现中,用户在线状态实际上是由一种叫session的东西来保存的。你可以理解为某种不可见的东西,用户带在身上,就表示登陆了,不在身上了,就登出了。

那么针对session这种抽象资源,如何应用REST规则呢?很简单。

首先,我们也许不需要看到有哪些用户在线,因此,针对sessionindex页可以不用考虑。

新建session资源的页面在哪儿呢?也许你已经想到了,那就是登陆页。实际上session的新建(new)就是用户输入用户名和密码那个页面,提交之后如果成功,那么就成功创建(create)了一个session资源。因此登陆后的页面就是sessionshow页面了——我们展示已登陆的用户的账号信息,其实质就是展示他身上带的session

大多数情况下用户不会修改自己的登陆状态——再说,又能改成啥呢?因此,你可以放心地把editupdate扔掉,最后,只剩下删除(destroysession的页面了,这就是logout

总结

记下这七个方法:indexshownewcreateeditupdatedestory。没事玩别人产品的时候多思考一下那些让你赞叹的产品是如何实现这七个方法的,以及哪些让你抓狂的产品是缺失了哪个方法导致你玩不顺畅的。你应该很快能够成长到避免一些初级错误的阶段。

例外

所有模式都是错的,但有些可以用。

如果你是在设计一个非常抽象也非常技术化的服务,比如设计一个OAuth服务的时候,要想明白其中的REST资源就比较困难,拿secret_key让用户去authorizen页授权再由后台去获取access_token,嗯,这超出大多数产品设计师的能力范围了,这也不奇怪,OAuth这样的“产品”本身就是由工程师设计出来的。这种情况下,你做好你能想像到的资源的设计,并相信你的技术团队能帮你搞定你想不出来的那部分就行了。

另外我相信牛逼的产品设计师不需要拿这七条去挨个校对,这世上就是那样一些人,他们丰富的经验和教训已经教会他们如何如何设计完整的产品流程并形成功能闭环,在说到删除destroy功能的时候他们还补充说到:不能真删除,做一个标记位把它标记为删除就行了,数据还要保存在我们数据库中,郭嘉要求要保留至少三个月以备查案底呢。

Comments