Search code examples
c#domain-driven-designn-tier-architectureddd-service

Another application architecture question


I am trying some DDD and I will try to describe in most simple manner what I have done.

Core project
The core project contains Entities, VO and domain services. For example I have User entity and UserRelation entity. I think we all know what is the User entity. The UserRelation contains information about how users are connected to each other like follow and connect(bidirectional follow). Because of that I have UserDomainService with stateless methods like Follow(user,user) and Connect(user, user).

public class User
{
    public string Name { get; set; }
    public string Username { get; set; }

    public void ChangeUsername(stirng newUsername)
    {
        ApplyEvent(new UserUsernameChanged(newUsername));
    }
}

public class UserRelation
{
    ctor(User1, User2, isBidirectional)
    public User User1 { get; set; }
    public User User2 { get; set; }
    public bool IsBidirectional { get; set; }
}

public class UserDomainService
{
    public UserRelation Follow(User user1, User user2)
    { 
        return new UserRelation(user1,user2,false);
    }
}

Repository Project

I am using NHibernate so I decided to not create such a project. Instead I am using NHibernate directly. For example, in my UI I get a user object from the DB, change it and then call session.Save(user).

The problem

If I want to do operation like follow I do this:

  • Get some info from DB
  • Call the Follow(user1, user2) from the service
  • Save the UserRelation object to the DB In the end the application code becomes a bit complex. Imagine if we want to use this code in 2-3 places and at some point we have to refactor it.

My solution
My solution is to create a ApplicationService project which will do the dirty work and force the consumer to use ApplicationService instead of using Entitties and Domain services directly

public class UserApplicationService
{
    ctor(UserDomainService userDomainService){}

    User GetUser(Guid id)
    {
        return NhibernateSession.Get(id)
    }

    public void Follow(Guid user1Id, Guid user2Id)
    {
        var u1 = GetUser(user1Id);
        var u2 = GetUser(user2Id);
        var userRelation = _userDomainService.Follow(u1,u2);
        NhibernateSession.Save(userRelation);
    }

    public void ChangeUsername(Guid user, string newUsername)
    {
        user.ChangeUsername(newUsername);
        NhibernateSession.Save(user);
    }
}

Is this application service good or bad? As you can see the new service act also as a repository so we can create a UserRepository class but lets skip that for now. What bothers me is the parameters in the two methods. They accept Guids and the service retrieves users from the DB. The other option is to pass directly User object. The ChangeUsername method is like the one from User entity + persistence.

Well, what do you think about this?


Solution

  • I personally don't see anything wrong, in fact this is how the company I work with has done it, as long as you abstract out the data access from that service it could be part of the business layer as a mediator between the data layer and the ui layer, it saves you from repeating yourself and making sure that any rules outlined for a certain operation fires.