Search code examples
c#asp.net-mvcdesign-patterns

Correct architecture for presentation objects that implement same interface


In the domain model of my project, I have a pending amount of classes that implement the same interface IProduct: Phone, Tablet, DataPackage, Accessory, etc.

I want different combinations of these products to be displayed on different product list pages. This means, that I get a List in the presentation layer from the domain layer. And now, I'm wondering what is the correct way of binding different views for each interface implementation.

I see two ways of doing that:

  1. Have a property\method in the IProduct interface that defines what view will be chosen when needed to display the product. On one hand, it helps to encapsulate display logic into the class and call something like product.Display() for each of the products. On the other hand, this causes to add some display logic into the domain model, which is not good from my point of view.
  2. In a presentation layer have a factory that analyzes the type of the product and binds correct presentation.

Which one is preferable? Maybe there is more patterns for doing that?


Solution

  • I'd propose to vary your first approach in order to avoid mixing presentation logic with the domain classes. You could add a product type identifier to IProduct and set up the views for the products after a certain scheme that contains the product type identifier. When showing a view for a product, you build the view name after the scheme and integrate the product type identifier.

    The advantage of this approach is that you'd follow a convention-over-configuration pattern that would not require to have an explicit configuration that maps the product types to a view.

    As for your second approach: Instead of having a large switch statement in the factory that maps a domain class to a view, you could add a registry that contains the view that is assigned to a specific type. This would be better extensible.

    Both approaches imply the risk that the presentation logic does not provide a view for a new domain class. You'd have to check whether a view (or registration respectively) exists for a product type in order to handle this properly. A possible way would be to provide a default view that shows the properties that are available in IProduct for all classes. In addition, you should log an clear error message for the developer/administrator (see this link for a method to check whether a view exists).