转:我们是否应该把后端构建为API
原文来自于:http://www.infoq.com/cn/news/2015/07/api-or-not
不久前,在StackExchange网站上,一位名为SLC的用户提起他正在设计一个ASP.NET网站,他对于是否要将后端设计为API有些举旗不定,希望能够得到一些建议。一石激起千层浪,这个帖子很快得到了大量的关注与回复。现在让我们来了解一下SLC所面临的具体情况与问题。
SLC设计的网站是一个典型的ASP.NET MVC应用,他在开发时使用的都是一些经典的MVC模式,即控制器、视图与模型的结合,在控制器的方法中调用某个Manager对象以获取数据并创建视图模型。本来没什么问题,但他的某位同事对此表示异议,认为这种代码的耦合性太强,如若要创建一个桌面版本的应用,这些代码就无法重用了。他所推崇的最佳实践是创建一套API,在此基础上开发网站、桌面应用或者移动应用就都不成问题了。
SLC对此看法持保留意见,他列举了几条他认为这种做法不合适的原因:
- 将后端设计为API有过度抽象之嫌,巨大的灵活性同时也意味着巨大的复杂度;
- MVC中的一些内置特性将变得无用武之地,例如与角色和认证相关的功能都要重新设计;
- 为了保证API调用的安全性,必须设计某种令牌系统,在每次API调用中都要附加相应的令牌;
- 整个程序中的每个功能都必须编写一个对应的API调用;
- 在API中无法利用接口或抽象类等工具,像WCF这样的框架对于接口的支持非常有限;
- 在桌面或移动应用中通常要避免细粒度的API调用,因此不得不为支持这些系统创建一些批量方法或粗粒度的方法;
- 这违反了YAGNI原则,除非你已确定要同时支持多种具备相同功能的应用,否则只是无谓地增加开发工作量;
- 由于无法实现端到端的单步执行,调试变得非常困难。
支持者
用户gbjbaanb坚决支持使用API设计后端的方式,他认为这种方法不仅使得代码可以重用,并且能够带来更高的安全性与更好的设计。而一体性的实现会造成架构的僵化,难以扩展、替换及改进。他还以时下最流行的微服务为例,在这种设计中的后端实现为多个小型的服务,它们各自提供一套API以供客户端进行调用。他同时也指出了SLC对于API的概念存在误解之处,API并非一种远程类库,而更像是一种提供数据的服务。网站可以通过API获取数据,并在本地对数据进行某些操作。
gbjbaanb也对SLC所列举的部分观点进行了点评:
- MVC本身就是遵循隔离服务概念的一种设计,只是ASP.NET MVC框架将这些设计元素组织在一起而已。因此使用API并不代表放弃了MVC思想,只是缺少了这一框架中的一些辅助方法。如果过于依赖这些辅助方法,就等于将自己绑定在这一框架上,这种情况下可以编写自己的辅助方法,或寻找一些第三方类库。
- 调试也一样简单。首先由于API是一个独立的层,因此完全可以对API进行隔离测试,这种情况下甚至不需要进行调试。如果确实需要进行端到端的调试,那么也可以打开多个Visual Studio,同时附加到多个进程上进行调试。
- 为了保证安全性而进行额外的设计,这其实是一件好事。如果将所有安全方面的代码都实现在网站中,一旦黑客攻破了Web服务器,就等于获得了所有访问权,包括数据库。而如果设置了一个额外的API层,那么安全性就可以大大提高。
gbjbaanb最后为SLC提了一些设计方面的建议,从分层架构的角度看,网站是一种展示层,而API则是应用层。对于业务逻辑的设计可以看情况选择以数据为中心,或是以领域为中心的方式,当然后者显得更“纯净”一些。
反对者
而反对API的声音也不少。fotijr表示虽然微服务是当下的热点,但这不代表这种做法总是值得的。松耦合固然是好事,但如果因此让整个开发周期变得过于痛苦,那就得不偿失了。他同时建议将模型放在一个独立的数据访问项目中,以便MVC或桌面应用可以直接重用。JacquesB也不支持设计为API的做法,他认为单纯地创建API并不能够保证松耦合性,如果设计不当,反而会出现跨服务器边界的紧耦合性。
一点拙见
接下来笔者将简单地表达一下对此问题的个人意见。首先是对API的理解,原作者似乎将API简单地理解为一种独立进程的分布式的API,例如Web API、Remoting或RPC调用。其实从广义上来说,只要是通过代码调用后台的业务逻辑与数据,都可以理解为一种API。因此问题不在于要不要设计API,而是如何设计这套API。
接下来看一下原作者的设计方式,他所使用的方法是在控制器方法内调用某个Manager对象的方法以访问数据,那么大概可以推测出他的业务逻辑是以一种以数据为中心的设计思想,所使用的模式很可能是事务脚本(Transaction Script)。这种方式的优点在于简单易懂,但这样设计出的模型很可能是一种贫血模型,即业务逻辑大量散落在对应于用例的应用层的方法中,随着时间的推移,其难以维护的缺点将会逐渐暴露出来。
比较好的方式是遵循关注分离的设计原则,将业务逻辑与对应用例的应用逻辑进行隔离,将业务逻辑放在一个具有高度内聚性的领域层中,而展示层(即网站、桌面或移动应用)通过应用层间接地调用相应的业务逻辑。从这一角度来说,SLC所需的API正是应用层所暴露的方法与对象(例如数据传输对象),而他本人在之后的回复中也表示了对这一点的理解。至于是否要将应用层的API设计为分布式,这已经不是主要的问题所在了。
关于通过API实现重用性,让同一套逻辑能够适用于不同的展示层,这一点笔者并不认同。诚然,在分层架构(或其它类似的架构)中,理论上是有可能重用相同的应用逻辑的。但在实际应用中,由于客户端的不同特性,往往会对应用逻辑进行某种程度的调整,以实现最优化的用户体验。在网站中使用的Composite UI风格,在移动端可能会被设计为Task Based UI,而UX以及用例的区别将直接导致应用层API的变化。如果要坚持重用应用逻辑,势必要对UX作出某种程度的妥协,在做出重用这一决定时,软件组织必须对它的影响有深刻的理解。
其实在笔者看来,分层的最大好处在于保持了设计与代码的整洁性,有利于长期的设计演变与代码维护,并且能够促进单元测试,同时可以对不同的层进行并行开发、测试与部署。相信这也是SLC的同事的本意所在。
转:我们是否应该把后端构建为API的更多相关文章
- 论Node在构建超媒体API中的作用
论Node在构建超媒体API中的作用 作者:chszs,转载需注明. 博客主页:http://blog.csdn.net/chszs 超媒体即Hypermedia,是一种採用非线性网状结构对块状多媒体 ...
- 在 .NET Core 中构建 REST API
翻译自 Camilo Reyes 2020年8月26日的文章 <Build a REST API in .NET Core> [1] REST API 可以使用简单的动词(如 POST.P ...
- Spring MVC中使用 Swagger2 构建Restful API
1.Spring MVC配置文件中的配置 [java] view plain copy <!-- 设置使用注解的类所在的jar包,只加载controller类 --> <contex ...
- php 使用 restler 框架构建 restfull api
php 使用 restler 框架构建 restfull api restler 轻量级,小巧,构建restfull api非常方便! 官网:http://restler3.luracast.com/ ...
- spring boot / cloud (三) 集成springfox-swagger2构建在线API文档
spring boot / cloud (三) 集成springfox-swagger2构建在线API文档 前言 不能同步更新API文档会有什么问题? 理想情况下,为所开发的服务编写接口文档,能提高与 ...
- 14.app后端如何设计api
app和后端的交互,一般都是通过后端提供的api实现.api的设计,估计很多刚进入app后端的小伙伴会一无头绪,不知道怎么入门.下面根据自己3年的app后端经验,总结出下几个api设计原则,给小伙伴参 ...
- 使用Express构建RESTful API
RESTful服务 REST(Representational State Transfer)的意思是表征状态转移,它是一种基于HTTP协议的网络应用接口风格,充分利用HTTP的方法实现统一风格接口的 ...
- SpringBoot 构建RestFul API 含单元测试
相关博文: 从消费者角度评估RestFul的意义 SpringBoot 构建RestFul API 含单元测试 首先,回顾并详细说明一下在快速入门中使用的 @Controller . @RestC ...
- Springboot 如何加密,以及利用Swagger2构建Restful API
先看一下使用Swagger2构建Restful API效果图 超级简单的,只需要在pom 中引用如下jar包 <dependency> <groupId>io.springfo ...
随机推荐
- ANT的安装和配置(windows)
1.下载:到ANT官方网站http://ant.apache.org/下载最新版本,解压后即可.2.配置环境变量:我的电脑----属性-----高级----环境变量 如:ANT_HOME:C ...
- Ubuntu14.04 固定IP
Ubuntu 固定IP 1. 更改/etc/network/interfaces的内容 1.1 注释掉原来的内容 1.2 添加以下内容 auto eth0 iface eth0 inet static ...
- 请列出你在从事IT生涯中,最难以忘怀的一次误操作
IT系统最怕什么,我觉得就两点: 1.不可靠的软硬件. 2.误操作. 第一点就不用解释了,第二点是该文的内容,主要摘选自ITPUB的精华贴——[精华] 请列出你在从事DBA生涯中,最难以忘怀的一次误操 ...
- day-1
/* 倒计时就要结束了 在机房的最后一个晚上 恩 就要结束了 上午考试 下午背板 找了几个原题敲了敲 晚上zjk老妈送的饭 撑死死死死了 好吃23333 吃饭完和zjk在机房门口楼梯上聊了一会 恩 以 ...
- ThinkPHP函数详解:R方法
R方法用于调用某个控制器的操作方法,是A方法的进一步增强和补充.关于A方法的用法见这里.R方法的调用格式:R('[项目://][分组/]模块/操作','参数','控制器层名称') 例如,我们定义了一个 ...
- HTML文本格式化
文本格式化标签: 标签 描述 <b> 定义粗体文本. <big> 定义大号字. <em> 定义着重文字. <i> 定义斜体字. <small> ...
- java内存分块
运行时数据区域 Java虚拟机在执行Java的过程中会把管理的内存划分为若干个不同的数据区域.这些区域有各自的用途,以及创建和销毁的时间,有的区域随着虚拟机进程的启动而存在,而有的区域则依赖线程的启 ...
- Dom操作--全选反选
我们经常会在网站上遇到一些多选的情况,下面我就来说说使用Dom写全选反选的思路. 全选思路:首先,我们来分析一下知道,当我们点击"全选"复选框的时候,所有的复选框应该都被选中,那我 ...
- android测试分析1
Android测试框架,开发环境中集成的一部分,提供一个架构和强有力的工具 可以帮助测试你的应用从单元到框架的每个方面. 测试框架有这些主要特征: 1.Android测试组件基于Junit.你可以使用 ...
- SomeThing of Memcache
Memcache for .net 文章一: http://blog.csdn.net/dinglang_2009/article/details/6917794 不定时更新