ServiceStack 零依赖请求-响应 DTO
ServiceStack zero dependency Request-Response DTOs
在阅读了一些 ServiceStack wiki 之后,我遇到了关于 DTO 的问题,我希望你能提供帮助。
wiki 说:
在服务开发中,您的服务 DTO 提供与技术无关的服务层,您希望保持清洁并尽可能 'dependency-free' 以实现最大的可访问性和潜在的重用。我们的建议是将您的服务 DTO 保存在一个独立的、基本上没有 dep 的程序集中。
(https://github.com/ServiceStack/ServiceStack/wiki/New-API)
最后,您还可以使用以前更明确的客户端 API(非常适合没有 IReturn<> 标记的情况):
(https://github.com/ServiceStack/ServiceStack/wiki/New-API)
基于以上原因,我认为关于ServiceStack的最佳实践是:
我们应该使用 POCO 请求-响应 DTO 而不是继承自 IReturn<>。?
例如:
我们应该使用 1#:
public class AuthenticationRequest
{
public string Name { get; set; }
public string Password { get; set; }
}
public class AuthenticationResponse
{
public AuthenticationResponseType Result { get; set; }
public UserInfoDto UserInfo { get; set; }
}
我们不应该使用 2#:
using ServiceStack;
public class AuthenticationRequest : IReturn<AuthenticationResponse>
{
public string Name { get; set; }
public string Password { get; set; }
}
public class AuthenticationResponse
{
public AuthenticationResponseType Result { get; set; }
public UserInfoDto UserInfo { get; set; }
}
因为1#是零依赖,所以2#对ServiceStack有依赖library/framework.
如果我把所有的Request-Response DTO打包成一个NET DLL,1#比2#更抽象!
这意味着:
如果将来有一天我决定不使用 ServiceStack,则此 DLL 不需要任何更改。 (ServiceStack library/framework 应该是基础架构而不是抽象)
如有错误请指正。
非常感谢。
DTO 唯一的依赖项应该是无实现的 ServiceStack.Interfaces.dll
,因为它是一个便携式 Class 库 (PCL) 几乎支持 .NET 的每个 mobile or Desktop platform运行。 ServiceStack 的 Interfaces .dll 是必需的,以便能够在一个单一的良性 .dll 中清楚地描述您的完整服务合同。
例如。 [Route]
元数据属性捕获托管远程服务的自定义路由,这是有关您的服务的必需信息,客户需要知道这些信息才能通过其发布的自定义路由调用服务。同样,IReturn<T>
接口标记提供了关于您的服务 returns 的强类型合同,这正是启用 ServiceStack succinct end-to-end Typed API 的原因。本质上 ServiceStack.Interfaces 是一个必需的扩展,以便能够在您的服务 DTO 中捕获您的整个服务合同。
ServiceStack.Interfaces 可以在 ServiceStack 之外使用
即使您不使用 ServiceStack,您仍然可以使用良性的 ServiceStack.Interfaces.dll
,客户端可以自省以找到有关您的 DTO 和远程服务合同的更多信息。虽然我没有看到任何理由,但如果您想分离项目中的 ServiceStack.Interfaces,您只需复制您在 DTO .dll 中使用的属性,将其从任何外部依赖项中释放出来。但这会影响您拥有通用服务客户端的能力,因为这些嵌入式接口和属性对于您的客户端库来说是未知的,从而限制了它使用它来启用丰富的通用功能的能力。
其他语言的服务契约接口和属性
为了支持 TypeScript 等非 .NET 语言,ServiceStack 在生成的 DTO 中发出这些接口,因此它们不需要任何依赖项。
同样在添加 ServiceStack 参考 support of Swift 2.0 or Java and Android 中,这些额外的合同是按照惯用方式发出的,引用 Swift IReturn
协议或 Java IReturn<T>
中的接口 android 客户端包,这也是启用简洁类型 API 的 ServiceStack 在 iOS 和 Android.
上启用的原因
服务设计
在设计 API 时应牢记的一点是 Service Layer is your most important contract。也就是说,您的 API 的存在是为了允许消费者访问您的远程服务器功能,因此您的内部逻辑应该是一个隐藏的实现细节,而不是应该影响 API 的外部表面积的东西。
Request DTO 定义了您的服务合同,我发现在其中使用 Request
后缀是一种丑陋的结构,会对外部 API 的可读性产生负面影响,例如这是带有 *Request
后缀的名词的典型示例:
var response = client.Get(new CustomerRequest { ... });
与使用请求 DTO 具有指示性并提供更好的服务功能可读性的动词相比:
var response = client.Get(new FindCustomers { ... });
您的请求 DTO 理想情况下应该是 动词 即 grouped by call semantics and Response Type。具有 *Dto
后缀表明您的内部实现正在泄漏并影响您的外部 API 消费者将绑定(并且永远不应更改)的理想服务合同。请记住,您的服务的 objective 是为您的消费者提供可重复使用的功能,因此您的 impl 应该实现您发布的合同,而不是相反,它的实现决定了合同应该是什么。
考虑到这一点,我会重写您的 ServiceStack 示例,使其看起来像:
public class Authenticate : IReturn<AuthenticateResponse>
{
public string UserName { get; set; }
public string Password { get; set; }
}
public class AuthenticateResponse
{
public AuthenticationResult Result { get; set; }
public UserInfo UserInfo { get; set; }
}
这最终类似于 ServiceStack 的内置 Authenticate
和 AuthenticateResponse
请求和响应 DTO。
我还建议阅读这个较早的答案以了解 。
在阅读了一些 ServiceStack wiki 之后,我遇到了关于 DTO 的问题,我希望你能提供帮助。
wiki 说:
在服务开发中,您的服务 DTO 提供与技术无关的服务层,您希望保持清洁并尽可能 'dependency-free' 以实现最大的可访问性和潜在的重用。我们的建议是将您的服务 DTO 保存在一个独立的、基本上没有 dep 的程序集中。 (https://github.com/ServiceStack/ServiceStack/wiki/New-API)
最后,您还可以使用以前更明确的客户端 API(非常适合没有 IReturn<> 标记的情况): (https://github.com/ServiceStack/ServiceStack/wiki/New-API)
基于以上原因,我认为关于ServiceStack的最佳实践是: 我们应该使用 POCO 请求-响应 DTO 而不是继承自 IReturn<>。?
例如:
我们应该使用 1#:
public class AuthenticationRequest
{
public string Name { get; set; }
public string Password { get; set; }
}
public class AuthenticationResponse
{
public AuthenticationResponseType Result { get; set; }
public UserInfoDto UserInfo { get; set; }
}
我们不应该使用 2#:
using ServiceStack;
public class AuthenticationRequest : IReturn<AuthenticationResponse>
{
public string Name { get; set; }
public string Password { get; set; }
}
public class AuthenticationResponse
{
public AuthenticationResponseType Result { get; set; }
public UserInfoDto UserInfo { get; set; }
}
因为1#是零依赖,所以2#对ServiceStack有依赖library/framework.
如果我把所有的Request-Response DTO打包成一个NET DLL,1#比2#更抽象!
这意味着: 如果将来有一天我决定不使用 ServiceStack,则此 DLL 不需要任何更改。 (ServiceStack library/framework 应该是基础架构而不是抽象)
如有错误请指正。
非常感谢。
DTO 唯一的依赖项应该是无实现的 ServiceStack.Interfaces.dll
,因为它是一个便携式 Class 库 (PCL) 几乎支持 .NET 的每个 mobile or Desktop platform运行。 ServiceStack 的 Interfaces .dll 是必需的,以便能够在一个单一的良性 .dll 中清楚地描述您的完整服务合同。
例如。 [Route]
元数据属性捕获托管远程服务的自定义路由,这是有关您的服务的必需信息,客户需要知道这些信息才能通过其发布的自定义路由调用服务。同样,IReturn<T>
接口标记提供了关于您的服务 returns 的强类型合同,这正是启用 ServiceStack succinct end-to-end Typed API 的原因。本质上 ServiceStack.Interfaces 是一个必需的扩展,以便能够在您的服务 DTO 中捕获您的整个服务合同。
ServiceStack.Interfaces 可以在 ServiceStack 之外使用
即使您不使用 ServiceStack,您仍然可以使用良性的 ServiceStack.Interfaces.dll
,客户端可以自省以找到有关您的 DTO 和远程服务合同的更多信息。虽然我没有看到任何理由,但如果您想分离项目中的 ServiceStack.Interfaces,您只需复制您在 DTO .dll 中使用的属性,将其从任何外部依赖项中释放出来。但这会影响您拥有通用服务客户端的能力,因为这些嵌入式接口和属性对于您的客户端库来说是未知的,从而限制了它使用它来启用丰富的通用功能的能力。
其他语言的服务契约接口和属性
为了支持 TypeScript 等非 .NET 语言,ServiceStack 在生成的 DTO 中发出这些接口,因此它们不需要任何依赖项。
同样在添加 ServiceStack 参考 support of Swift 2.0 or Java and Android 中,这些额外的合同是按照惯用方式发出的,引用 Swift IReturn
协议或 Java IReturn<T>
中的接口 android 客户端包,这也是启用简洁类型 API 的 ServiceStack 在 iOS 和 Android.
服务设计
在设计 API 时应牢记的一点是 Service Layer is your most important contract。也就是说,您的 API 的存在是为了允许消费者访问您的远程服务器功能,因此您的内部逻辑应该是一个隐藏的实现细节,而不是应该影响 API 的外部表面积的东西。
Request DTO 定义了您的服务合同,我发现在其中使用 Request
后缀是一种丑陋的结构,会对外部 API 的可读性产生负面影响,例如这是带有 *Request
后缀的名词的典型示例:
var response = client.Get(new CustomerRequest { ... });
与使用请求 DTO 具有指示性并提供更好的服务功能可读性的动词相比:
var response = client.Get(new FindCustomers { ... });
您的请求 DTO 理想情况下应该是 动词 即 grouped by call semantics and Response Type。具有 *Dto
后缀表明您的内部实现正在泄漏并影响您的外部 API 消费者将绑定(并且永远不应更改)的理想服务合同。请记住,您的服务的 objective 是为您的消费者提供可重复使用的功能,因此您的 impl 应该实现您发布的合同,而不是相反,它的实现决定了合同应该是什么。
考虑到这一点,我会重写您的 ServiceStack 示例,使其看起来像:
public class Authenticate : IReturn<AuthenticateResponse>
{
public string UserName { get; set; }
public string Password { get; set; }
}
public class AuthenticateResponse
{
public AuthenticationResult Result { get; set; }
public UserInfo UserInfo { get; set; }
}
这最终类似于 ServiceStack 的内置 Authenticate
和 AuthenticateResponse
请求和响应 DTO。
我还建议阅读这个较早的答案以了解