通过一组RESTful API表露CQRS系统效率

转载:medium

命令和查询责任分开(CQRS)是由Greg
Young提议的一种将系统的读(查询)、写(命令)操作分离为二种独立子系统的架构形式。命令平时是异步执行的,并蕴藏在一个事务型数据库中,而读操作则通常是终极一致的,并且数据出自于解正规化的视图。

前几日,我想为设计人员解决一个很普遍的题材:登录,注册和密码苏醒UX。这多少个题目会影响退出页面的快慢,当然还会潜移默化到转会。

本文在此提议并为读者显示一种为CQRS系统成立一套RESTful
API的措施。这种措施组成了HTTP的语义、REST
API基于资源的风格,并能够处理分布式总计的一点问题,例如最后一致性和并发性。

你应有考虑二种境况:

此外大家还提供了一套原型API,它成立于Greg
Young编写的m-r
CQRS原型之上,后者也被喻为SimplestPossibleThing。m-r可以认为是CQRS原型的事实标准,它刺激了很多团体利用并创办CQRS系统。即便这么些m-r原型很简短,但它曾经可以显得在现实世界中运用RESTful
CQRS系统的少数机遇和挑衅了。

– 电子商务网站,用户数据只是非凡关键;

俺们在将下局部审阅m-r的圈子模型,随后对有关特性的API设计进行局部探索。最后,大家将对一部分所做的取舍展开探究,并且商讨一些RESTful
m-r的定义和辩论内容。

– 网站和网络应用程序,用户音信可以是可选的。

m-r领域

m-r模型是一个由此简化的库存管理类别的领域模型,你可以成立新库存物品(假如它是某类别型的成品),重命名或注销激活(即逻辑删除)它们。被吊销激活的物料将不再为用户所见,而具有移动的物品都可以被拿走,并且可以见到各类物品的装有细节。你也可以扩大或调减这些库存物品,指定所投入或裁减的物品数量。换句话说,在创立库存量之后,就足以起来应用这多少个系统了。

用户将透过共同的查询来查阅物品列表或是物品细节,对于物品情状的修改将通过命令来实现。在具体世界中,命令应该是异步执行的,但鉴于代码中利用了内存中的风波总线(伊夫nt
Bus)及事件处理函数,由此在终极促成中命令都是共同执行的。

图片 1

m-r模型实现了CQRS:命令和询问被分级存储在不同的地点,并且各自由系统中全然两样的有些开展处理。

除了CQRS之外,m-r也应用了事件源自(伊芙(Eve)nt
Sourcing)作为它的持久化机制。在这种艺术中,对于世界模型的改动会被擒获为一多元的风波,那个事件会按照它们被调用的顺序存储起来。为了赢得某个模型的此时此刻景观,需要将具备事件依照它们发出的逐条举办重放。换句话说,模型中实体的意况信息是不会被持久化的。举例来说,假使我们创立了一个库存物品,随后将它重命名三遍,那么我们将会拿到一个InventoryItemCreated事件和五个InventoryItemRenamed事件,那多少个事件都会被保留在事变存储(伊夫nt
Store)中。

事件是接连的,并且每个事件都蕴含一个版本号,用以在并发时举办检查。举例来说,假如某个库存物品在本子2的底蕴上展开重命名,但恰恰有另一个重命名暴发在同一个物料上,并使它的方今版本变为3,那么那种情状就会招致出现非凡。

命令与世界事件层出不穷是一定的涉及,当调用了某个命令之后,领域模型会发起并蕴藏一个事件。领域事件是事件本源的木本,它和跨四个边界上下文(bounded
context)的轩然大波不同,往往粒度更细,并且只包括所需的微乎其微数量的信息。由此,它并不是一个适合于在不同的界线上下文之间展开集成的工具。除了行使一个经过内的轩然大波总线之外,m-r还用到了一个内存中的风波存储。那些蕴藏本质就是一个哈希表,它利用模型的id作为键,并且不断跟踪模型中暴发的任何事件。

如欲领会CQRS和事件起点的更多音讯,你可以翻阅Greg
Young的这本迷你书

报到和注册UX老是很惨痛。没有人欣赏通过填写表单、检查和验证电子邮件、编写严苛依照规则的新密码来注册新网站。

创设一套上层的REST API

只要您赞成于先去感受一下最后的贯彻,可以在此地看一下一个当下(暂时性)可运行的原型。大家鼓励你使用fiddler或者浏览器自带的开发工具去检查一下这一个简单的示范中的HTTP请求。在GitHub上得以找到包括这套API和一个主干的Angular应用的源代码。不过大家如故要强调,它的兑现模式和利用的技巧并非关键所在,读者更应有关爱于统筹模式及HTTP的显示。

在你不记得在注册过程中采用的密码时,会时有暴发稍微次?我无数时刻忘记,需要还原它。

当面领域的布局

对此这些API层来说,最根本的权利是将底层的领域建模为资源,并透过HTTP语义透流露来。在那多少个历程中,API层将开创一个公物领域,它由资源(以及它们的唯一标识符->URL)以及输入和出口的音信所组成。底层的小圈子越简单,这么些公开领域和底部领域的一般程度就越高。

(单击图片以松开)

图片 2

在这一个事例中,我们成立的公然领域与底层的天地如故相比相似的,但不怕是这种简单的圈子,大家也不可知直接将底层的世界表暴露来:这恐怕造成领域的中间贯彻被外泄出去,而且世界里面也不必然带有API层所需的总体性能。比方说,所有的内部命令都会用一个整数来表示并发时所需的版本号,而在明面儿领域中则用字符串意味着这多少个特性。我们稍后将会动用那一个特性作为ETag,而据悉HTTP规格要求,ETag必须是不透明的。

简简单单的话,大家所创办的精通领域表现了内部的小圈子类,但又不完全相同。这种公开领域经常被叫做一个视图模型(Vide
Model)。这些术语并不太规范,因为那种表明形式感觉上对公开领域有些排外,将它视为一种“哑”模型,由此我们赞成于选用一个新术语“输出模型”(output
model)。它将被采纳到输入和输出音讯中(命令和输出模型)。

在移动装备上,报到和注册用户体验比在电脑上更痛苦。因为用户必须切换应用才能确认电子邮件,或者切换键盘以找到特殊字符。

资源

大家很当然地想到应该有一个InventoryItem资源,因而我们将世界中的这些单根实体透露为一个单身的资源,可以用/api/InventoryItem福利地开展表示。每个库存物品将用/api/InventoryItem/{id}进展表示,m-r使用了全局唯一标识符(GUID)作为Id。

动用这么些独立的根对象就足以完整的显示大家的世界了。还有一种方法是运用/api/InventoryItem/{id}/Stock本条资源作为丰盛和删除库存量(即签入或移除物品)的形式。从实质上说它们从不什么高下之分,无非是哪一类艺术可以更好地显示资源而已。由于第一种方法更为简便易行,因而大家就应用这种方法。

(单击图片以推广)

图片 3

Houston大学拓展的一项研究标志,在手机方面,人们频繁花费两倍的岁月输入密码,与此同时,他们会在统计机上安装的密码会相对简单。

查询

我们需要多个查询:GetInventoryItemsGetInventoryItemDetails。那里我们将因此三个GET方法/api/InventoryItem/api/InventoryItem/{id}表透露这四个查询效能。

GetInventoryItems主意可以拿走仅包含了物品名称Id的一个列表,它会基于ACCEPT头决定回到JSON或是XML(ASP.NET
Web
API可以襄助这一效能)。假诺某个资源符合于缓存,那么具有的GET请求都有可能回到缓存数据。GetInventoryItems返回InventoryItemListDataCollection用作出口信息。即使可以经过数量内容的哈希生成ETag,不过这里我们挑选将列表中每一项的Id名称拓展哈希后取得的结果作为ETag重回给客户端(例如浏览器)。客户端可以采用将资源缓存起来,并针对性ETag使用If-Non-Match展开规范请求。大家选用将资源的max-age设为0,因而客户端的GET会始终使用规则请求,不过也足以拔取安装一个人造的晚点时间。

GET /api/InventoryItem HTTP/1.1 
Accept:application/json, text/plain, */* 
Accept-Encoding:gzip,deflate,sdch 
If-None-Match:"LdHipfxR7BsfBI3hwqt2BLsno8ic98KmrIA1y67Nnw4="

回到结果

HTTP/1.1 304 Not Modified 
ETag: "LdHipfxR7BsfBI3hwqt2BLsno8ic98KmrIA1y67Nnw4="

GetInventoryItemDetails方法会重回某个库存物品的细节,包括IdNameCurrentCount属性,最终一项属性记录了现阶段的库存数据。即使其间领域的读取模型(read
model)包含了版本号,但假如将某个数值类型的版本号直接作为ETag会时有暴发安全性问题,因为客户端可以擅自地猜出下一个数值。因而,我们挑选了应用高级加密标准(AES)对版本号举办加密后,作为InventoryItemDetails方法的ETag输出。

为每个操作都再次实现ETag对于API层来说多少负担过重,因而我们定义了一个IConcurrencyAware接口:

public interface IConcurrencyAware 
{ 
    string ConcurrencyVersion { get; set; } 
}

各种补助ETag的出口模型都要实现这些接口,当API层看到某个输出模型支撑那个接口时,就会读取版本号并设置ETag值。另一方面,当API层对条件式GET请求举行响应时,会将转移的ETag与客户端在If-None-Match头中传入的值举行相比较。所有那个操作都可以经过一个单身的全局filter实现:ConcurrencyAwareFilter

急需留意的是,添加、删除或者重命名某个库存物品时应有使物品列表的缓存失效。请看下面的事例(条件式GET请求的逻辑是在浏览器端完成的,不需要专门编写代码实现):

GET /api/InventoryItem HTTP/1.1 
If-None-Match:"CWtdfNImBWZDyaPj4UjiQr/OrCDIpmjVhwp8Zjy+Ok0="

回去结果是一个状态码为200的完全响应,并且带有了一个新的ETag值:

HTTP/1.1 200 OK 
Cache-Control:max-age=0, private 
Content-Length:68 
ETag:"0O/961NRFDiIwvl66T1057MG4jjLaxDBZaZHD9EGeks=" 
Content-Type:application/json; charset=utf-8; domain-
model=InventoryItemListDataCollection; version=1.0.0.0; 
format=application%2fjson; schema=application%2fjson; is-text=true 
...

请留心Content-Type头包含了附加的参数,这是对于“传媒类型的五种级别”(或者简称5LMT)概念的一种实现,这种办法不是将持有音信都塞到一个独立的令牌(token)中,而是利用不同的参数来发挥对用户有用的不等级此外数码,能够发挥不同级其它有用信息。下文会对这些核心做更加的商量。

怎么着立异注册UX

命令

询问普通会映射到GET方法,而下令则需要映射到POST、PUT、DELETE和PATCH方法。将HTTP谓词映射到CRUD操作是一种流行的思想意识,但在真正世界中很少可以将谓词和数据库操作一一对应。实际上,REST
API并不在对持久化存储之上的一个简短包装,相反,它是指点用户去探听事情领域、操作与工作流的一扇门。因而它必须可以不借助于于特定的谓词去表达某个维度的用意。

一种普遍的措施是应用远程过程调用(RPC)风格的资源,例如/api/InventoryItem/{id}/rename。虽然它看起来确实去除了对某种谓词的借助,但它违反了REST面向资源的变现能力。大家需要记住,资源是一个名词,HTTP谓词则表示动词和动作,而自描述的信息(REST的主题之一)则是发挥此外维度音讯和企图的招数。实际上,在HTTP新闻中所包含的指令就活该可以描述任什么人为的操作了。不过,完全依赖于请求体中的音信也有它和谐的题材,因为请求体平日是作为流传递的,要在辩认出它的具体操作以前得到整个请求体有时是不容许做到的,而且那也不是一种明智的做法。这里,我们将显得一种基于5LMT中的第4级别(即世界模型)处理请求的措施,命令的类型将富含在Content-Type头中的某部参数内。

PUT /api/InventoryItem/4454c398-2fbb-4215-b986-fb7b54b62ac5 HTTP/1.1  
Accept:application/json, text/plain, */* 
Accept-Encoding:gzip,deflate,sdch 
Content-Type:application/json;domain-model=RenameInventoryItemCommand

这般就可以将请求正确地输送给服务端相应的处理办法了。这这种格局是否将过多的信息泄露给客户端了吧?并非如此。输入输出信息的schema(以及名称)是公开领域的一部分,客户端必须可以完整地走访到它,由此它们凭借于schema也是在我们所预期的。

至于客户端的落实只用了最少量的代码,这里运用了一个AngularJS*的装饰(decorator)封装了$http服务,它可以读取这一个原型的回到内容,并且可以在Content-Type头中参与额外的参数音讯。只要保持JavaScript构造函数*的名称不变就不曾问题。

俺们早已解决了辨认当前正被调用的主意的问题,接下去需要将下令遵照语义映射到相应的HTTP谓词。在将指令映射到谓词时,选取正确谓词的最重要不仅仅在于语义,同样要考虑幂等性(至于谓词的安全性则无需顾忌,因为任何一个下令谓词都是不安全的)。PUT、PATCH和DELETE是幂等的,而POST则不是幂等的(多次调用一个幂等的谓词的结果与仅调用一回是均等的)。

1 – 描述注册给用户的补益

众人通过成立帐户拿到咋样?注册有哪些利益?例如:

CreateInventoryItemCommand

从CRUD范式的角度来说,CreateInventoryItemCommand很自然地适用于POST方法。(这里只显示重要的头新闻)

POST /api/InventoryItem HTTP/1.1 
Content-Type:application/json;domain-model=CreateInventoryItemCommand  

{"name": "CQRS Book"}

回到的响应如下:

HTTP/1.1 202 Accepted 
Location: http://localhost/SimpleCQRS.Api/api/InventoryItem/
109712b9-c3d5-4948-9947-b07382f9c8d9

该操作将在location头信息中回到那些将被成立的库存物品(因为所有操作都是异步执行的)的URL地址。

2 – 添加另外注册模式

这是一种可以更快地报了名的点子。你可以采用社交登录或谷歌。

防止输入并记住密码;这是立异那一个历程的好情势。即使有用户喜好标准的电子邮件注册。

DeactivateInventoryItemCommand

如同前文所述,裁撤激活库存物品就表示两遍逻辑删除。其它,删除操作是幂等的,因为频繁去除一个库存物品的功能和一遍删除是平等的。由此大家将拔取DELETE选项作为撤消激活某个物品的法门(该办法包含一个空的方法体)。

DELETE /api/InventoryItem/f2b75f21-001a-4eed-b8f3-35bf5e4e9b0d HTTP/1.1 
Content-Type:application/json;domain-model=DeactivateInventoryItemCommand  

{}

回到的响应如下:

HTTP/1.1 202 Accepted

虽说也得以在方法体中传送id,但在URL中早已提供了id音信。DeactivateInventoryItemCommand构造函数的绝无仅有任务是不易地安装domain-model其一参数。

3 – 注册表格应该唯有最少的材料

少即是多!从UX的角度来看,要求电子邮件和密码就充裕了。

制止在这么些等级询问,如性别,出生日期或其余不是必需的信息。您可以随时要求用户在个人资料页面中添加更多音信。

RenameInventoryItemCommand

RenameInventoryItemCommand比起任何命令来说更好玩一点。首先,重命名一个库存物品也就是举行修改,因此使用PUT谓词是最合适的。另一方面,即便您正在重命名某个物品时,你的同事也在尝试将其重命名为另一个名字的话会如何呢?这就是一个出现问题。HTTP通过If-Unmodified-SinceIf-Match提供了对资源举办并发修改时的保障体制。因为我们运用了ETag,因而就相应地设置If-Match

PUT /api/InventoryItem/f2b75f21-001a-4eed-b8f3-35bf5e4e9b0d HTTP/1.1 
Content-Type:application/json;domain-model=RenameInventoryItemCommand 
If-Match:"DL1IsUoH709K+N5TXFzlQeQI5arO8r/U0SzXcRhuXLc="  

{"newName": "CQRS Book 1"}

AngularJs的controller会传递ETag值,并传播模型中,之后在规则式PUT请求时进行利用。如您所见,ETag的值仅仅是对世界模型中版本号的一种表现,但我们对其进展加密以满足HTTP规格的需要。服务端获取到那些值之后进展解密并还原成版本号的数值。如若版本号不匹配,领域模型就会抛出一个ConcurrencyException异常,在API层的ConcurrencyExceptionFilterAttribute类捕获到这些可怜之后,会以HTTP语义的模式显示该特别。

HTTP/1.1 412 Precondition Failed

本条例子很好地表明了HTTP的面世怎么着与CQRS的现身检查体制相结合。

4 – 不要再一次字段

绝不在注册表中有再度这多少个字段。

譬如说:多少个密码字段,两个电子邮件字段等

CheckInItemsToInventoryCommand和RemoveItemsFromInventoryCommand

那三个指令就越来越有意思了。大家将往库存中投入或删除一些物料。从某方面来说,这种操作是对库存物品的数码举行翻新,因而得以将其促成为一个PUT(也许PATCH更适用)方法。但因为这多个指令并非幂等(比如说,调用CheckInItemsToInventoryCommand一次应该加上一回库存),由此最契合的谓词实际上是POST。

客户端将在Content-Type头音讯中的参数中安装领域模型的称号,如同我们事先所见的如出一辙。

POST /api/InventoryItem/f2b75f21-001a-4eed-b8f3-35bf5e4e9b0d HTTP/1.1 
Content-Type:application/json;domain-model=CheckInItemsToInventoryCommand  

{"count": "230"}

归来的响应是均等的:

HTTP/1.1 202 Accepted

5 – 不要要求用户通过电子邮件确认他们的挂号

这一步很紧要。

对此某些公司来说, 在阳台上证实用户是不行重大的。

考虑到您能够经过发送电子邮件来验证它们,但让她们稍后再实践,
并能够采纳系统有着机能。通过电子邮件的表明过程可以在接下去的几天内完成。

在那种情形下, 您必须认同凭证,
制止用户只好切换应用程序使用另外服务。一个好的做法是短信验证:用户将因此短信接收代码,可以轻松地键入,而无需切换应用程序(在移动装备上)或切换网页(在微机上)。

切换环境在UX中是不佳的做法。用户可能会迷失方向,这或者会滋生障碍,最后可能会堵住他们达到其前期的目的。

HTTP的其他方面

实现HTTP的有些另外地点也会带来一些好处,HEAD也是一个至关首要的谓词,它的响应结果和GET方法一致,但重临的响应体中不包括其他内容。我们为具备GET资源都落实了HEAD谓词,例如:

HEAD /api/InventoryItem HTTP/1.1 
Accept:application/json, text/plain, */* 
Accept-Encoding:gzip,deflate,sdch

将返回

HTTP/1.1 200 OK 

ETag: "LdHipfxR7BsfBI3hwqt2BLsno8ic98KmrIA1y67Nnw4="

切实在贯彻中会将HEAD请求转向给GET方法的处理函数,而框架本身会在最后负责移除重回的情节。这一多重实现都是机关触发的,因而在响应中可以正确地赢得ETag。

另一个内需实现的重点谓词是OPTIONS,这个谓词可以用于生成API文档,但是大家那边只是简短的回来该资源协理的所有谓词:

OPTIONS /api/InventoryItem/f2b75f21-001a-4eed-b8f3-35bf5e4e9b0d HTTP/1.1

它将再次来到如下内容:

HTTP/1.1 200 OK 
Allow: GET,POST,OPTIONS,HEAD,DELETE,PUT 
Content-Length: 46 
Content-Type: application/json; charset=utf-8; domain-model=String%5b%5d; version=4.0.0.0; 
format=application%2fjson; schema=application%2fjson; is-text=true  

["GET","POST","OPTIONS","HEAD","DELETE","PUT"]

请留心,响应中的Allow头对于OPTIONS请求来说是必须的。然而HTTP规格本身并没有点名OPTIONS响应体中现实写法,因而我们就将允许的谓词作为一个字符串数组重回(注意,在domain-model参数中的String[]是经过UrlEncoded办法编码的结果)。可以动用那些谓词生成符合各样schema和言语要求的API文档。

除了那个办法之外的任何调用都会回来一个方法未找到(method not
found)
或者405状态码,ASP.NET Web API自身已经落实了这一功能:

PUT /api/InventoryItem HTTP/1.1  

{}

它将赶回:

HTTP/1.1 405 Method Not Allowed 
Allow: POST,GET,HEAD,OPTIONS  

{"message":"Http Method not supported"}

什么样改正密码UX

改正密码中的用户体验是一个自身想和其外人分享的话题。

密码在UX中真正很痛苦。

讨论

这一部分将详细讲述某些理论概念,以及我们的决定中一些比较困难,或者可能引起争议的部分。

6 – 不要采纳太多的平安规则

有微微次你会觉得编写“安全”密码很无聊?有多少次你不可能在网站上利用你“最常用”的密码?因为它不带有符号或数字。

自己认为明日在网站上的安全性万分重要。在50三个网站上举办重复寻找我发现里面90%的用户仅使用两个或两个密码限制,并且在过去几年中尚无密码安全题材。

我实在指出您的网站接纳以下两个或多少个规则:

密码必须含有数字;

密码必须包含大写字母;

密码必须至少有一个@#$符号;

长度必须超出8个字符;

密码不应包含字符串;

密码无法包含重复。

可选的产出检查

在m-r最初的贯彻中,所有命令(除了CreateInventoryItemCommand,它早已隐式地蕴藏了值为0的版本号)都包含一个整数型的CurrentVersion字段。而以此本子大校它们修改为可选的(即C#中的可空类型)。

在一面,服务端应该负责保证自己处境的完整性。因而它不可能、也不应当依靠于客户端所提供的版本号。并发检查是用作一个表征提供给客户端的,而不是服务端用以保证模型完整性的编制。要是客户端关心并发行为,这它就足以接纳性地发送版本号,这已经因此在ETag中的加密消息提供给它们了。要切记的是,并发检查与服务端的风波版本号是见仁见智的定义,后者是服务端的内部贯彻机制。

一方面,对于一些操作来说,并发检查是绝非意思的。举例来说,假如五个客户端在同一时间(调用CheckInItemsToInventoryCommand主意)添加了20个库存物品,并且它们都富有版本号n,那么内部有一个限令就会失利,但这种失败是不必要的,因为我们实在需要充分40个物品。那种题材在高访问量的气象下会被加大。想象一下,倘若大度的用户涌入Amazon网站去选购哈利波特的新星一期,在大部状态下她们都会赶上并发问题。

在HTTP中施行PUT(和PATCH)操作时会认为出现是一个可选的检查,那或多或少毫不偶然。虽然出现检查可以异步执行,但我们需要着力确保它必须共同执行,由此当大家再次来到状态码202(已接受)时,就象战胜务端已经认同了没有出现争持情形的暴发。

7 – 添加体现/隐藏密码的选料

向用户提供此选项在UX中相当好。用户观察他俩打字时会少犯错误。

媒体类型的五种级别(5LMT)和创立新的传媒类型

在社区里周边的一种做法是创立新的媒体类型,平日称为制作新的传媒类型。举例来说:

Content-Type:application/vnd.InventoryItemListDataCollection.1.0.0.0+json;

那种应用异乎经常的点子意味着某个媒体类型的子类型已经变为了一种通用的推行(已经实际变成一种约定了),它将子系统分解为局部特定的、或者是业内的元素,并由此+号连接在一道。已经有点经过登记的媒体类型应用了这种约定,例如application/rss+xmlapplication/atom+xml。这六个示范处于媒体类型级别中的第3级别(或者叫做schema级别),而application/xml则处于第2级别(format级别)。某种意义上说,application/atom+xml就是一种application/xml项目,它们选拔同样的format,而前者还指明了会动用ATOM
schema。

虽说这一约定会在以后版本的HTTP规格中收获认同,但它并未缓解媒体类型不断增进的题目。首先,使用其他未注册的传媒类型都是HTTP规格所不提倡的,使用上述品种的Content-Type值也是相同。实际上,若是大家需要在装有API中为多少个不等媒体级其它肆意组合都登记一种媒体类型,那互联网号码分配局(IANA)恐怕需要动员一大批人去专门从事那多少个范围宏大的天职了。另一方面,许多客户端系统使用基于dictionary的传媒类型去处理这种请求,它们将无法应付新创建的传媒类型。

为此采用5LMT能够允许现有的客户端继续依照事先的方法正常工作,而更先进的客户端则足以应用更高级另外音讯,它们都是用作独立的实体提供的。

8 – 不要要求用户输入五遍密码

看来,在注册UX部分,不要有再度的字段。

通过一个当众的圈子保障内部领域是关键所在

将服务端的中间贯彻举行抽象对客户端的话是相当关键的。如同往日所述,为较小的世界所开创的公开领域和中间领域会比较一般,但虽然是在m-r这一个示例中,我们也不可知将内部领域直接表露出来,而必须创立一个单身的模子,它表现了客户端可以接受和交互的信息

咱俩还应有将公开领域文档化,并显示给客户端。这一派的开展值得关注,因为已经有各类不同的不二法门和推行开首呈现水面了(从WADL到Swagger、RAML和RestDown等等)。

9 – 添加密码强度计

前几天有那个概括的JS脚本可以轻松添加到您的网站,并得以改进密码的UX。

应用此脚本,用户可以实时查看安全级别,并促进可视化(如颜色:红色,蓝色,肉色)。

结论

不只通过一套REST
API暴露CQRS是唯恐的,而且HTTP语义的充裕性也使得我们能够在它的根底上编制一套流畅而卓有功效的API。整个流程包括创建一个由命令和询问(输入输出音讯)组成的当众领域,以及可以处理并发和缓存的各个资源。此外,我们还需要将中间领域的查询和下令映射为HTTP谓词,并且动用状态码以表现境况转换和特别。使用5LMT将促进创立完全RESTful,而不是长途过程调用风格的资源。所有这么些都得以透过一个很小但能够运行的原型应用举行显示,该原型是由此ASP.NET
Web API和AngularJS实现的。

10 – 预先体现密码限制,并实时更新

Mailchimp有其一很好的效率。我简直爱上它。

有关作者

图片 4Ali Kheyrollahi
是一位解决方案架构师、作者、博主、开源软件的撰稿人和贡献者,如今供职于伦敦的一家大型电子商务公司。他对HTTP、Web
API、REST、DDD和概念模型抱有极大的热心。而在拍卖实际的事务问题上又坚贞不屈实用性。他在这一行已有12年以上的阅历,并在六个出色公司工作过。他对于电脑视觉和机械学习世界具有深厚的志趣,并且已经宣布了多篇论文。在后面,他曾是一名医生,并作为一名非专科医师工作了5年。可以在此地找到他的博客,另外她在twitter上也特别活跃,可以透过@aliostad关注他。

查看原文地址:Exposing CQRS Through a RESTful
API

什么样立异登录UX

改进登录的UX是本文的末梢一部分。

11 – 使用社交账号登录

这与社交账号注册是一律的。

12 – 允许人们使用指纹认证登录。

通过这种措施,您可以减轻登录过程中的痛苦。TouchID可以形成,因为现在有80%的智能手机可以实现。

13 – 添加呈现/隐藏密码的精选

相同的想法,我在下面注册部分说过。

而是,显示密码不需假诺默认选项。这是会让用户感到不安全。

自身的指出是用经典标记“*”覆盖密码,让用户挑选显示/隐藏。

14 – 有忘记密码?链接

很少使用的密码日常被淡忘,应该在此外登录过程中都可以过来他们。

这是极品的密码復苏过程应该什么工作:

15 – 无密码登录

很少有店家尝试立异跳过输入密码此过程。

咱俩该肿么办啊?多少个例证:

用google验证器:link

短信识别号码:例如与Twilio

给用户一个附加的挑选,以防他们不想输入密码:“Magic
Link”从Slack是一个很好的例证,你可以结合到你的网站使用Auth0

生物识别认证:这是本文中最具创意的一块。确定登录和注册的前程将是UX。一些例证是:语音识别,面部扫描,指纹,眼睛扫描等。

总结

为你的网站设计登录和挂号的极品用户体验:

– 即便您有电子商务,请考虑客人结帐;

– 假诺您的业务根本在手机中,则使其非凡简单化;

– 描述注册给用户的便宜;

– 添加社交账号注册和登录;

– 表格应该只有必要的情节;

– 不要再一次字段;

– 考虑不同的章程声明用户(电子邮件或短信)


立异密码UX:不要添加太多的平整,突显规则给他俩看,添加展现/隐藏选项,不要输入一遍密码,添加强度计;

– 允许尚未密码的备用登录情势:生物识别和双因素认证;

Credits for this article
to:Gartner,Nielsen
Norman
Group
,Baymard

Leave a Comment.