-1

I have got an MVC application in which the Domain Model (Data Model + Business Model) resides in a different class library. I am using an interface exposing some methods which must return data but not necessarily the entire representation of my domain objects.

My question is How should I return the data?
Should I create a kind of view models on the Business Model layer and then match them with my real view models on the main application (views-controllers-viewmodels)?
Should I return this data as dynamic objects?
Should I return the entire domain object event I need a couple of properties only?
What is the best approach to follow?

This is an example to give a better idea about the situation:

//Domain Class
public class User
{
   public string UserName { get; set; }
   public int UserId { get; set; }
   public string UserPassword{ get; set; }
   public string FirstName{ get; set; }  
   public virtual ICollection<ApplicationUserTeam> ApplicationUserTeams
    {
        get { return _applicationUserTeams; }
        set { _applicationUserTeams = value; }
    }     

}


public interface ITrackAttendance
{
  dynamic GetUsersCompany(int CompanyId);

}

 public class TrackAttendanceServices : ITrackAttendance
{
    //Method returning a Dynamic Object???
    public dynamic GetUsersCompany(int CompanyId)
    {

        using (var _ctx = new TrackAttendanceDb())
        {
            return _ctx.Users.Where(u => u.ApplicationUserTeams.FirstOrDefault().Team.CompanyId== CompanyId)                    
                .Select(u =>
                         new
                          {
                            UserName = u.UserName,
                            UserId = u.Id,
                            userState = false

                         }).ToList();


        }

    }

}

Project Architecture:

enter image description here

My Solution:

Thanks to all the experts who have given their opinion for this question, I have decided to follow a DTO approach (@uk2k05) base on the following aspects:

  • It allows me to keep a very clean architecture.
  • This approach is more in line with the single Responsibility principle
  • It ensures that my application layer isn't dependent upon an underlying domain model.

I have to acknowledge the other interesting approaches raised here, such as the Factory Pattern(@Liam) and command-query separation (CQS)(@L-Four), both of them are useful to deal with the problem but they could add extra complexity and work to my specific environment. CQS and FP require a mind shift for defining the architecture (from my humble and personal opinion).

D.B
  • 4,009
  • 14
  • 46
  • 83
  • 1
    Why would you return domain model entities for queries? Why not separate commands from your queries, and simply bypass the domain layer for queries. – L-Four Jul 04 '16 at 12:58
  • sorry, but i do not what u mean. Could you please be a bit more explicit or maybe an example? Thanks. – D.B Jul 04 '16 at 13:02
  • I think what your trying to do here could be better solved by a [Factory pattern](https://en.wikipedia.org/wiki/Factory_method_pattern). You create a factory, you call the factory to return you an object. You use this object in your controller (possibly converting into a ViewModel depending on the implmentation). That said your question is very unclear. For example what part of this is supposed to be the repository pattern? – Liam Jul 04 '16 at 13:05
  • Best practice, is not to expose database objects to your view layer.. To keep things simple write your Business logic so that it returns Data Transfer Objects which are representations of your query results. Pass these to your View layer and from this create your View Model objects – uk2k05 Jul 04 '16 at 13:11
  • Don't use DTOs...[DTOs are an Anti pattern.](http://stackoverflow.com/questions/1440952/why-are-data-transfer-objects-an-anti-pattern) @uk2k05 your solution will mean the same data will need to be created in 3 seperate objects (the model, a DTO and a Viewmodel). How is this best practice? – Liam Jul 04 '16 at 13:16
  • @liam DTO's are not an anti pattern per se. Read a bit more on abstraction and CQS; and the other answers in that post that you mention. – L-Four Jul 04 '16 at 13:23
  • All anti patterns have some uses. The term "anti pattern" is typically used when a pattern (with a niche implementation) is abused. DTOs are abused a lot. If your not exposing your objects to external resources and you don't need to maintain consistency, don't use them. They add unneccasry complexity and overhead. As I said, how does adding a DTO help here? It doesn't. It's certainly ridiculous to suggest that everyone should use *x pattern all the time*..Patterns solve problems, they are not rules to follow blindly – Liam Jul 04 '16 at 13:34
  • Indeed. Therefore, when applying CQS, it's very useful. – L-Four Jul 04 '16 at 13:40
  • 1
    well guys I am bit confuse, basically I was trying to avoid to expose my objects to the the application layer (not create a reference to that library here) and at the same time, not duplicate my business objects creating a kind of "view models" in the domain layer (I guess this DTOs definition) which seems to me a bit redundant. just want to know how you return part of your entities to your controllers (without query the db from the controllers). – D.B Jul 04 '16 at 13:49
  • Ok, why don't you want to expose your objects to the business layer? What does that achive? If the answer is *well nothing really I just thought that was the right thing to do* then stick to the [KISS principle](https://en.wikipedia.org/wiki/KISS_principle) and just expose your object. What harm does it cause? My guess is none? If you have a particular goal here then you need to explain what that goal is. Like I said above, patterns are tools to fix problems, not rules to follow. – Liam Jul 04 '16 at 14:43
  • 1
    Thanks @Liam, There are apparently very good reasons for using the Factory Pattern. However, as with the CQS principle, however I can not see the right environment to be applied yet. I decided to stick to DTS approach because of the reasons exposed in my updated question. (PS: @ Liam, it was a pity you deleted your first answer, it was really useful.) – D.B Jul 05 '16 at 14:14
  • Well you got there in the end, so that's the important thing. Glad to of helped – Liam Jul 05 '16 at 14:22
  • Well I don't think that the DTO usage is a big problem. The biggest problem I see is that you are using and returning anonymous types. So you are basically returning a dynamically created projection (subset of the User class). So what is your reason for doing this? Limitation of the properties can also be archived with an interface. So that can not be the real reason. Only the line "userState = false" is something that cannot be archived with standard OOP techniques. So what is the meaning of this line? Does this "userState" have a business meaning or is it just some technical requirement? – Frank Jul 08 '16 at 09:16

1 Answers1

1

Have a look at command-query separation (CQS). Basically it means you split the query side from the command side.

For commands, like updating of creation of entities, you go through the domain model as you are probably doing now.

However, for queries, there is no need to go through the domain layer as you are not altering the system in any way, just retrieving information. Therefore, you can simply bypass the domain layer, query the database directly and return (projected) data entities; which in your controllers are then mapped to the dedicated view models and passed to the views. With projected, I mean that you don't expose your data layer directly, but DTO's that are constructed based on it; which could look completely different than your domain model entities.

Lots of information to be found about it, for example read here.

L-Four
  • 13,345
  • 9
  • 65
  • 109
  • but, It would imply to query the database directly from the controllers ? I created a class library for my business logic in order to have a layer who deal with the database. – D.B Jul 04 '16 at 13:19
  • No, you would have a query side next to your command side. The query side could be a regular class library as well, just as you have a class library for your domain model. – L-Four Jul 04 '16 at 13:21
  • 1
    Thanks @LFour . This approach is really interesting and I would like to explore it on further detail in order to determine when it can be really used. For my specific environment i decided to go with a DTS approach for simplicity. – D.B Jul 05 '16 at 14:07