1

After reading some ServiceStack wiki, I have a problem about DTO and I was hoping you could help.

The wiki said:

  1. In Service development your services DTOs provides your technology agnostic Service Layer which you want to keep clean and as 'dependency-free' as possible for maximum accessibility and potential re-use. Our recommendation is to keep your service DTOs in a separate largely dep-free assembly. (https://github.com/ServiceStack/ServiceStack/wiki/New-API)

  2. Finally you can also use the previous more explicit client API (ideal for when you don't have the IReturn<> marker): (https://github.com/ServiceStack/ServiceStack/wiki/New-API)

According to the reasons above, I consider the best practice about ServiceStack is: We should use POCO Request-Response DTOs instead of inheriting from IReturn<>.?

For instance:

We should use 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; }
}

We shouldn't use 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; }
}

Because 1# is zero dependency, 2# have a dependency on ServiceStack library/framework.

If I package all Request-Response DTOs to a NET DLL, 1# is more abstract than 2#!

This means: If one day in the future I deceide not to use ServiceStack, this DLL doesn't need any change. (ServiceStack library/framework should be Infrastructure not Abstraction)

Please correct me if I am wrong.

Very thanks.

chansey
  • 1,266
  • 9
  • 20

1 Answers1

1

The only dependency DTO's should have is the impl-free ServiceStack.Interfaces.dll which as it's a Portable Class Library (PCL) supports almost every mobile or Desktop platform that .NET runs on. ServiceStack's Interfaces .dll is required in order to be able to cleanly describe your complete Services contract in a single, benign .dll.

For example. the [Route] metadata attribute captures the Custom Routes where the remote Services are hosted which is required info about your Service that clients need to know in order to be able to call services via their published Custom Routes. Likewise the IReturn<T> interface marker provides a strong-typed contract on what your Service returns which is what enables ServiceStack succinct end-to-end Typed API. Essentially ServiceStack.Interfaces is a required extension to be able to capture your entire Service Contract in your Services DTO's.

ServiceStack.Interfaces can be used outside of ServiceStack

Even if you don't use ServiceStack, you can still use the benign ServiceStack.Interfaces.dll which the clients can introspect to find out more information about your DTO's and the remote Service Contract. Whilst I'm not seeing any reason to, if you want to decouple the ServiceStack.Interfaces on your project you can just copy the attributes you're using in your DTO .dll freeing it from any external dependencies. But this would impact your ability to have a generic Service Client since these embedded interfaces and attributes are unknown to your client library, limiting its ability to enable rich generic functionality using it.

Service Contract Interfaces and Attributes in other Languages

To support non .NET languages like TypeScript, ServiceStack emits these interfaces in the generated DTO's so they don't require any dependencies.

Likewise in Add ServiceStack Reference support of Swift 2.0 or Java and Android these additional contracts are emitted idiomatically referencing a Swift IReturn protocol or IReturn<T> interface in the Java android client package which is also what enables the succinct Typed API's ServiceStack enables on both iOS and Android.

Service Design

Something you should keep in mind when designing your API's is that your Service Layer is your most important contract. i.e. Your API exists to allow consumers access to your remote Servers capabilities, so your internal logic should be a hidden impl-detail, not something that should impact the external surface area of your API.

The Request DTO defines your Service Contract where I find using a Request suffix is an ugly construct that negatively affects the readability of your external API, e.g. Here's a typical example of what a noun with a *Request suffix would look like:

var response = client.Get(new CustomerRequest { ... });

Compared with using a Verb where the Request DTO is indicative and provides better readability of what the Service does:

var response = client.Get(new FindCustomers { ... });

Your Request DTO should ideally be a verb that's grouped by call semantics and Response Type. Having a *Dto suffix is an indication that your internal implementation is leaking and affecting the ideal Service Contract your external API Consumers will bind to (and should never change). Keep in mind the objective of your Service is to provide re-usable functionality to your consumers so your impl should realize your published contract, not the other way around where its implementation dictates what the contract should be.

With that in mind I would rewrite your ServiceStack Examples to look like:

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; }
}

Which ends up being similar to ServiceStack's built-in Authenticate and AuthenticateResponse Request and Response DTOs.

I also recommend reading this earlier answer to understand the importance of DTO's and how it relates to the goals of a Service.

Community
  • 1
  • 1
mythz
  • 141,670
  • 29
  • 246
  • 390
  • Great answer for this question, thanks mythz. But I still confuse about Why not use a *Dto suffix for UserInfo? IMO, UserInfo in AuthenticateResponse should be DTO instead of domain entity (eg: ORM entity in EF). – chansey Oct 11 '15 at 10:58
  • Request- Response DTOs contain ORM entity? (I think it's not good idea.) Please correct me if I am wrong. Very thanks. – chansey Oct 11 '15 at 11:01
  • @chansey Please read my last link on [importance of DTOs and how OrmLite clean POCOs differ from Heavy ORMs](http://stackoverflow.com/a/32940275/85785), ultimately do whatever you feel comfortable with, but you should have a good reason to force additional restrictions, code, friction and complexity on yourself, i.e. don't just follow blanket rules blindly without reason, make sure you know why they add value. – mythz Oct 11 '15 at 11:23
  • @chansey `*Dto` is not the ideal name for a published Service Contract, it's your most important model i.e. the only one your consumers see and bind to and should be free and decoupled from any impl concerns. `*Dto` is an ugly suffix that's indicative that it's a projection of your internal implementation whereas your implementation should be a realization of your Service contract. Your external DTOs should contain the ideal names which your impl then implements. – mythz Oct 11 '15 at 11:54
  • About *Dto suffix, It seems that your recommand use POCO entity in Request-Response DTO. But IMO, some complex POCO entity maybe has some behaviour in its aggregate root (e.g: calculate price). But in the client's perspective, it only need data not behaviour. Therefore I prefer convert dto "to model" "to viewmodel" and vice versa. – chansey Oct 11 '15 at 14:03
  • About this question (zero dependency), I still have question about IReturn marker: when we said the name "DTO", "the DTO self is POCO". Is this right? (IMO, POCO shouldn't inherit from other framework's interface or attribute) I'm really confused.....(If you think its a new question, I can ask a new question.) – chansey Oct 11 '15 at 14:04
  • 1
    @chansey DTOs are what the Service serializes, they should be clean, benign data structures that doesn't have any logic in them, i.e. like the Data Models you would use with OrmLite, Redis, etc. If you're not using ServiceStack libraries or a Micro ORM, then yeah don't re-use your Data Models and copy them into purpose-specific DTOs - which are just serializable POCOs. – mythz Oct 11 '15 at 14:15