如何给老婆解释什么是Restful

作者: 柳树之 | 来源:发表于2017-10-28 08:13 被阅读16174次

    老婆经常喜欢翻看我订阅的技术杂志,她总能从她的视角提出很多有趣的问题。

    一个悠闲的周日下午,她午觉醒来,又习惯性的抓起这个月的杂志,饶有兴趣地看了起来。

    果不其然,看着看着,她又对我发难了,“Restful是什么呀,老公?是restaurant的形容词吗,突然就觉得好饿了啊......”

    作为一个合格的程序员,我一直把能够将一项技术讲给老婆听,并且能给她讲懂,作为我已经掌握了这项技术的标准。
    如果我直接回答说,“REST就是Representational State Transfer的缩写呀,翻译为中文就是‘表述性状态转移’”,那她今晚肯定得罚我跪键盘。我必须找个合适的机会,把Restful的来龙去脉给她形象的描述一遍。

    “走,咱们去楼下咖啡厅吃个下午茶吧”,我对老婆说。

    “一个芝士蛋糕,一杯拿铁,两条吸管,谢谢”,我对前台的服务员说,然后我们找了个角落坐了下来。

    Level 0 - 面向前台

    “刚才我们向前台点了一杯拿铁,这个过程可以用这段文字来描述”,说着,我在纸上写下了这段JSON,虽然她不知道什么叫JSON,但理解这段文字对于英语专业8级的她,实在再简单不过。

    {
        "addOrder": {
            "orderName": "latte"
        }
    }
    

    “我们通过这段文字,告诉前台,新增一笔订单,订单是一杯拿铁咖啡”,接着,前台给我们返回这么一串回复:

    {
        "orderId": "123456"
    }
    

    “订单ID?还是订单编号?”
    “恩恩,就是订单编号”
    “那我们就等着前台喊‘订单123456的客户可以取餐了’,然后就可以开吃了!”
    “哈哈,你真聪明,不过,在这之前,假设我们有一张会员卡,我们想查询一下这张会员卡的余额,这时候,要向前台发起另一个询问”,我继续在纸上写着:

    "queryBalance": {
            "cardId": "886333"
        }
    }
    

    “查询卡号为886333的卡的余额?”
    “真棒!接着,查询的结果返回来了”

    {
        "balance": "0"
    }
    

    “切,没钱......”
    “哈哈,没钱,现在我们要跟前台说,这杯咖啡不要了”,我在纸上写到:

    {
        "deleteOrder": {
            "orderId": "123456"
        }
    }
    

    “哼,这就把订单取消啦?”

    Level 1 - 面向资源

    “现在这家咖啡店越做越大,来喝咖啡的人越来越多,单靠前台显然是不行的,店主决定进行分工,每个资源都有专人负责,我们可以直接面向资源操作。”
    "面向资源?”
    “是的,比如还是下单,请求的内容不变,但是我们多了一条消息”,我在纸上画出这次的模型:

    /orders
    
    {
        "addOrder": {
            "orderName": "latte"
        }
    }
    

    “多了一个斜杠和orders?这是什么意思?”
    “这个表示我们这个请求是发给哪个资源的,订单是一种资源,我们可以理解为是咖啡厅专门管理订单的人,他可以帮我们处理所有有关订单的操作,包括新增订单、修改订单、取消订单等操作”
    “Soga...”
    “接着还是会返回订单的编号给我们”

    {
        "orderId": "123456"
    }
    

    “下面,我们还是要查询会员卡余额,这次请求的资源变成了cards”

    /cards
    
    {
        "queryBalance": {
            "cardId": "886333"
        }
    }
    

    “接下来是取消订单”
    “这个我会”,说着,她抢走我手上的笔,在纸上写了起来:

    /orders
    
    {
        "deleteOrder": {
            "orderId": "123456"
        }
    }
    

    Level2 - 打上标签

    “接下来,店主还想继续优化他的咖啡厅的服务流程,他发现负责处理订单的员工,每次都要去订单内容里面看是新增订单还是删除订单,还是其他的什么操作,十分不方便,于是规定,所有新增资源的请求,都在请求上面写上大大的‘POST’,表示这是一笔新增资源的请求”

    “其他种类的请求,比如查询类的,用‘GET’表示,删除类的,用‘DELETE’表示”

    “还有修改类的,修改分为两种,第一种,如果这个修改,无论发送多少次,最后一次修改后的资源,总是和第一次修改后的一样,比如将拿铁改为猫屎,那么用‘PUT’表示;第二种,如果这个修改,每次修改都会让这个资源和前一次的不一样,比如是加一杯咖啡,那么这种请求用‘PATCH’或者‘POST’表示”,一口气讲了这么多,发现她有点似懂非懂。

    “来,我们再来重复上面那个过程,来一杯拿铁”,我边说边画着:

    POST /orders
    
    {
        "orderName": "latte"
    }
    

    "请求的内容简洁多啦,不用告诉店员是addOrder,看到POST就知道是新增",她听的很认真,理解的也很透彻。
    "恩恩,返回的内容还是一样"

    {
        "orderId": "123456"
    }
    

    “接着是查询会员卡余额,这次也简化了很多”

    GET /cards
    
    {
        "cardId": "886333"
    }
    

    “这个请求我们还可以进一步优化为这样”

    GET /cards/886333
    

    “Soga,直接把要查询的卡号写在后面了”
    “没错,接着,取消订单”

    DELETE /orders/123456
    

    Level 3 - 完美服务

    “忽然有一天,有个顾客抱怨说,他买了咖啡后,不知道要怎么取消订单,咖啡厅一个店员回了一句,你不会看我们的宣传单吗,上面不写着:

    DELETE /orders/{orderId}
    

    顾客反问道,谁会去看那个啊,店员不服,又说到,你瞎了啊你......据说后面两人吵着吵着还打了起来...”
    “噗,真是悲剧...”

    “有了这次教训,店长决定,顾客下了单之后,不仅给他们返回订单的编号,还给顾客返回所有可以对这个订单做的操作,比如告诉用户如何删除订单。现在,我们还是发出请求,请求内容和上一次一样”

    POST /orders
    
    {
        "orderName": "latte"
    }
    

    “但是这次返回时多了些内容”

    {
        "orderId": "123456",
        "link": {
            "rel": "cancel",
            "url": "/order/123456"
        }
    }
    

    “这次返回时多了一项link信息,里面包含了一个rel属性和url属性,rel是relationship的意思,这里的关系是cancel,url则告诉你如何执行这个cancel操作,接着你就可以这样子来取消订单啦”

    DELETE /orders/123456
    

    “哈哈,这服务真是贴心,以后再也不用担心店员和顾客打起来了”

    “订单123456的客户可以取餐了”,伴随着咖啡厅的广播,我们吃起了下午茶,一杯拿铁,两支吸管......

    对程序员的话

    用了大白话,给老婆讲明白了RESTful的来龙去脉,当然,我还是有些话想说的,只是怕老婆听完一脸懵逼,没给她说:

    1、
    上面讲的Level0~Level3,来自Leonard Richardson提出的Richardson Maturity Model

    richardson-model.png

    Level0和Level1最大的区别,就是Level1拥有了Restful的第一个特征——面向资源,这对构建可伸缩、分布式的架构是至关重要的。同时,如果把Level0的数据格式换成Xml,那么其实就是SOAP,SOAP的特点是关注行为和处理,和面向资源的RESTful有很大的不同。
    Level0和Level1,其实都很挫,他们都只是把HTTP当做一个传输的通道,没有把HTTP当做一种传输协议

    Level2,真正将HTTP作为了一种传输协议,最直观的一点就是Level2使用了HTTP动词,GET/PUT/POST/DELETE/PATCH....,这些都是HTTP的规范,规范的作用自然是重大的,用户看到一个POST请求,就知道它不是幂等的,使用时要小心,看到PUT,就知道他是幂等的,调用多几次都不会造成问题,当然,这些的前提都是API的设计者和开发者也遵循这一套规范,确保自己提供的PUT接口是幂等的。

    Level3,关于这一层,有一个古怪的名词,叫HATEOAS(Hypertext As The Engine Of Application State),中文翻译为“将超媒体格式作为应用状态的引擎”,核心思想就是每个资源都有它的状态,不同状态下,可对它进行的操作不一样。理解了这一层,再来看看REST的全称,Representational State Transfer,中文翻译为“表述性状态转移”,是不是好理解多了?

    Level3的Restful API,给使用者带来了很大的便利,使用者只需要知道如何获取资源的入口之后的每个URI都可以通过请求获得,无法获得就说明无法执行那个请求

    现在绝大多数的RESTful接口都做到了Level2的层次,做到Level3的比较少。当然,这个模型并不是一种规范,只是用来理解Restful的工具。所以,做到了Level2,也就是面向资源和使用Http动词,就已经很Restful了。Restful本身也不是一种规范,我比较倾向于用"风格"来形容它。如果你想深入了解Level3,可以阅读《Rest in Practice》第五章。

    2、
    我跟老婆讲的时候,用的数据格式是JSON,但是要强调一点,Restful对数据格式没有限制,就算你用的是XML或者其他格式,只要符合上面提到的几个特征,也算Restful。

    3、
    关于如何写出好的Restful API,阮一峰老师已经写过一篇非常棒的文章:RESTful API 设计指南,这篇文章将指导你写出优雅的Restful。

    4、
    我老婆长什么样子?
    看来是时候晒一下了:

    我是谁?
    没错,正是在下:

    啥?什么梗?
    欢迎关注《大雄和静香的故事》:

    这篇已经是第五集啦,上集中的tiny-facebook项目,已经加入了RESTful接口,代码已更新到Github,tag是v2.0,checkout一下就可以拿到代码啦,欢迎加星~~~

    参考

    相关文章

      网友评论

      • HitC:看个技术文章还被虐的不要不要的:unamused:
      • 3c41e44877cc:生动有趣
      • 守候流星雨:理解了是一个层次,能够写出来又是一个层次,讲得有理有趣的又上升了一个层次,学习了😇😇
      • AWeiLoveAndroid:这个思路不错 给大佬点赞,我写了一篇《通过春节参加宴席引发的设计开发App的深层次思考》 欢迎观看 https://www.jianshu.com/p/5e3c7b4ef37d
      • 51ddfd6dbcc9:故事真好
      • 95c92f44dffe:我使用AWLive推流,为什么会非常卡呢?rtmp://ossrs.net/live/123456789
      • 像酒:厉害了
      • android0226:楼主功底深厚
      • willing001:首先,
      • 6c9b0f154de5:有老婆的程序员不是好程序员
      • f13913dafd44:写的还是很形象的,不错的程序员!
      • 编码亦术:是不是有很多程序员向往你这样的生活,向往你有这么可爱的老婆么
      • 梧桐树边羽:居然看完了……
      • 顾空城:在csdn也看到了:smile:,还有程序员竟然有老婆,惊讶脸
      • 鱼十二:我又看不懂,我竟然还看完了😇
      • opleon:生动又简洁,很有趣
      • 554eb7540b89:好棒啊!
      • sh99:突然覺得程序猿也挺可愛的
      • dbf813e43eb8:这个世界上只有差的老师 从来没有教不会的学生 赞题主 我一直想零基础数学不好的我学点计算机技术 但是没有遇到一个好老师
      • 经纬文学:我的静香
      • fe93f3d70e08:不错,😀 帮你转转。
      • 小鱼儿他老汉:感觉文章还是有些长。
      • 小鱼儿他老汉:嗯,我也想娶这么一个,希望她不会我说第二句的时候就打哈欠。
      • wecode:棒棒的
      • ef40b2b9e6ec:楼主会玩的
      • 奔IV程序猿:感觉你老婆是袁方
      • 无人像妳i:很通俗易懂
      • 江边鸟74:厲害了,我的哥
      • e6b50dfe79d2:程序猿哪来的对象,自己new的嘛:joy:
        e6b50dfe79d2:@陆霁完全靠想象:joy:
        陆霁: @浪漫老狼 有意思
      • 亭子青年:我也想做这样的静香。

        感觉自己遇到了一个假老公。。。。。。
      • 欧巴冰冰:首先你要先有个老婆,,还不够,老婆应该还必须8级才能像作者那样可以直接说JSON.:smile:
        欧巴冰冰:8级指的是 英语8级
      • 月光流沙:你很厉害啊
      • BBBBean:好喜欢感性的理性思维
      • 陈小窝:缺个程序员老公:relaxed:
        事过境迁_17d4:@陈小窝 睡得真晚呀
        陈小窝:@事过境迁_17d4 没人讲解啊,还缺个:smiley:
        事过境迁_17d4:这是什么梗
      • 尴尬狮:厉害厉害
      • IchDich:好有意思
      • 风逐叶:简单来说,就是通过修饰过后的url请求服务器资源,让url更优雅简洁,并且屏蔽服务器资源的实际名称。
      • lionel880:趣味性十足,一般的人只是要脑海有个大致的印象,深入的人自然会去深入。
      • 玛西子:看来我在这条路上要走的路还很遥远:smile:
      • pnews88:有文学气息的理科生,真是把知识和现实生活结合起来,寓教于乐啊。
      • 最怕认真:大雄睁开眼就能看到静香的。。。。胖次(捂脸)
      • 不管啦做自己:我的法语过了专八,也好想要个程序员啊😁
      • 板栗大大:@gio33 这个好玩!
        板栗大大:@gio33 赶紧让你老公效仿一下:smile:
        gio33:@Flora910504 这个,我那脑袋,理解起来有困难
      • 41d210e60ce7:我发现活跃在简书的程序猿不是点把点,是很大一坨
        64d1c38fa6de:@慰我心忧我是贵州的 感觉你也是
        4b4d42e9a1bb:为毛用坨这个词呢,
        fe93f3d70e08: @慰我心忧 我也是其中之一😛
      • 梦中一点心雨:我也想给老婆说,前提先得有个老婆😂
      • AWeiLoveAndroid:博主写的真生动 其实也可以去顺便看看我的博客 http://www.jianshu.com/p/84568e364ee8
      • 抓蛙行者:我就缺这样一个女票
      • 5fb09c0c4833:6666666666
      • _小田:有点意思
      • xiangtan:离婚的jie zou
      • JavaXu:赞!我也一直认为,只有能向完全没编程或计算机基础的人讲清楚某项技术,才是真正掌握了。
      • 7hriller:我老婆通常只是礼貌性的问一下,其实根本没兴趣。
      • Rubyman:好有爱的日常生活
      • d12093189d78:这解说真形象
      • 旅兔seven:666 文科生表示终于看懂代码了哈哈哈哈
      • 黑色蜘蛛侠:讲的如此形象生动,看来是真理解透了
      • 举个nut:一杯拿铁两根吸管:sleepy:看到这里捂紧了我受伤的小心脏
      • 三个米连:写的很好啊,关注了,最近正好在公司负责REST的一个项目的性能优化
      • 李守俊:我老婆是资深女rd。
      • serinaScript:我是女程序员
      • 羽翼小球:程序员祝幸福的事情应该就是教会了女朋友或者老婆写代码,这是一种病。不过有一个喜欢听你说一堆推理,然后事实证明不是这个bug的原因的女朋友,肯定很幸福,肯定要带她吃好吃的,带她去巴黎,带她去墨尔本。带她过上既能朝九晚五又能周游世界的生活。我敢这么说的原因是我觉得我可能找不到对象。
        羽翼小球:@侠女一枝 你咋这气人呢?你好好的好不?
        羽翼小球:@侠女一枝 有你们我觉得我改不会沦陷到AI手里~
        羽翼小球:@侠女一枝 多么让人沮丧的选项…
      • 远见为识:我是小白,我来取经。不过还没入门,算是路过。谢谢分享
      • 883a847183f4:首先得找一个聪明肯看书的女人,否则你懂太多都没用
      • 漫城烟火:首先得有个老婆
      • 宋偲瑄:哇 超羡慕诶
      • 眼睫毛眼睫毛:看来最急切的问题是:我竟然没有老婆!
      • 叮宕:有老婆真好,你好细心啊。别人让我解释restful,我都是一句答非所问的回答:表征状态转移关键在于资源的识别、表述、转移……
        识别的功力在于需求的分析;表述在于合适项目,json\xml什么都可以;转移就是HTTP协议的那几个方法了……
        v587的毅哥:@叮宕 作者也就假拿个老婆的对象好让小白轻易入门有带入感而已,你还当真了
      • x_zhaohu:看见 SexyCode 的这个 ID , 忽然想起昨天在爱奇艺上看的电影 《扫黄》, 里面提到了 sexy.com,有兴趣的话,可以去看看,这里就不剧透啦,哈哈。
      • x_zhaohu:文中的楼主的老婆,在那找的?我也想去找找,哈哈。
      • 白貓:挺有意思的👍👍👍
      • 绰号陆拾柒:程序员居然有老婆!
      • 轻的像呼吸:很有新意
      • 麋鹿姑苏:好好玩呀
      • 不爱说话的乔歌:原来restful是这么理解的啊,那url和uri有什么区别嘞
        Mr_Treasure:URL 统一资源定位符
        URI 统一资源标识符
        不爱说话的乔歌:url是后面的部分
        叮宕:包含。 [scheme:]scheme-specific-part[#fragment] 比如http://jianshu.com,这里的scheme是http,其它也行,凡能唯一标识资源就是uri,url是他的一个具体的
      • 北京程序猿:github blog
      • 北京程序猿:哎哟,不错哟
      • 若锦:有点意思:joy::joy:
      • 音苍:是我静香不够骚了,还是你胖虎眼光高了。
        亭子青年:是胖虎变了
        爱读书的代码羊:我觉得我把依赖注入看的感觉污了,才发现自己长大了
        柳树之: @音苍 静香毁童年😀
      • Lionad_Guirotar:程序员有老婆嘛哼哼 别想啦
        柳树之: @Lionad_Guirotar 可以在虚拟机里有😂
      • 日丶月丶明:首先要有个老婆
        叮宕:@SexyCode exception:myWife对象创建失败。请使用单例,否则系统会自动把你的资料发给检察院,并用重婚罪起诉。
        日丶月丶明:@SexyCode 果然只有程序员懂
        柳树之: @日丶月丶明 Wife myWife = new
        Wife() 😂

      本文标题:如何给老婆解释什么是Restful

      本文链接:https://www.haomeiwen.com/subject/gcgdpxtx.html