DTOs and Response Classes – Interfaces vs Concrete Types

cserializationweb-api

Had a discussion that i felt i needed some external input on. Normally always use interfaces instead of concrete types (on lists, injectable services and so forth). For example in lists i just pass around IEnumerable instead on List and so forth. The same applies for custom types (ICustomClass instead on CustomClass). This works fine for webapi, logging frameworks like serilog and so forth.

But i ran into some custom code which couldnt handle serializing interfaces due to implementation details. The argument for keeping concrete types instead of interfaces (and instead of adjusting serialization) was summarized to this post. And i can see if you work with XML documents there might be a need for concrete types to ensure serialization / deserialization if that is required (?).

EDIT: Realized i might have been unclear / vague in my description. I
personally would never Create an interface for a DTO itself (like
IDTO). Since i do not see any point to it. I likely will never replace it and i dont inject it for example. I WOULD however often resort to have that DTO contain an IEnumerable property in favor of a List or Type[] for example. I cant remember any time ive had an custom class represented by an interface since i ntry to always keep them simple. But perhaps there is a scenario i could raise regarding this where the same questioning might persit.

Soo what i would gladly get some input on:

Is there any good concrete technical arguments for avoiding interfaces in DTOs and responses (that might be serialized when returned through api or logdumping for example) in a normal REST API that outputs json?

Best Answer

In general, you want to accept as abstract a type as possible, and return as concrete a type as possible, but the situation you came across isn't really a question of abstract vs. concrete types. If you want the caller to be responsible for making sure an argument is serializable, that needs to be specified in the interface. That means requiring both IList and something like ISerializable.

Alternately, you could implement the serialization yourself using just the IList interface. However, not all ILists are serializable. How would you serialize an infinite list, for example?

That being said, the C# syntax for parameters that require multiple interfaces is inane. There's a YAGNI argument to be made that do you really need to support everything that implements IList? Is it worth the trade off in readability?

Design principles need to be balanced, so sometimes it's okay to give up a little abstraction in order to gain clarity.