Domain Driven Design (Asp.Net Core) - working around with private encapsulation Back

Domain Driven Design (Asp.Net Core) - working around with private encapsulation

Posted on 3/10/2021 under tech .net domain-driven-design

Domain Driven Design has been around for some time. Been a minimalist kind developer who prefer to keep things simple and clean by keeping anything unnecessary out, I always felt that DDD or CQRS are stuff that are just good to have. Maybe I'm wrong, they may be great for bigger projects, but for smaller project you may want to re-consider as they incur much more development time.

In theory, Domain Driven Design advocates modeling based on the reality of business as relevant to your use cases. I'm not going to talk so much about the theory here, in reality the technical concepts of DDD means most of your business domain logic are withtin your domain classes and fields are been set private, something like this:

public class Tenant : Entity, IAggregateRoot

{

        private string _name;

        private string _description;

 

        protected Tenant() { }

 

        public Tenant(string name, private string _description, Guid userId)

        {

            _name = name;

            _description = description;

 

            // inherit from parent class - Entity

            SetCreatedBy(userId);

            SetUpdatedBy(userId);

        }

 

        public void SetName(string name, Guid updatedById)

        {

            _name = name;

            SetUpdatedBy(updatedById); // will call SetUpdatedDate()

        }

 

        public void SetDescription(string description, Guid updatedById)

        {

            _description = description;

            SetUpdatedBy(updatedById); // will call SetUpdatedDate()

        }

In order to manipulate the values of name or description, you would need to use SetName() or SetDescription() methods via the object itself, doesn't seems have a problem here.

var tenant = await _repo.tenants.GetByGuidIdAsTracking(request.Dto.Id);

 // update - name, updatedBy, updatedTime

 tenant.SetName(request.Dto.Name, request.UserId);

You probably building a asp.net core web api where entitties are retrieved/persisted across database with ef core framework and entities would be returned as a result. If you are new to DDD, you will probably encounter these common issues.

1. Private fields cannot be directly accessed via ef core database context in a linq statement

2. The domain class when return directly from an api controller as a api result will not have the private fields indicated in the returned result

For problem number 1,  just use the EF.Property as provided by ef core framework.

return await _context.Tenant

     .Where(t => EF.Property<string>(t,"_name").Equals(name))

    .AsNoTracking()

    .FirstOrDefaultAsync();

      

For problem number 2, you probably can map it to a DTO class with public fields and return the DTO class as the api result instead of directly returning the domain class as the result set. You probably want to use automapper in this case. 

I happen to found out that the below GetName() function will map the value of private field _name to the destination object field name. Somehow asp.net core has this mapping to a shadow property mapping built in. 

private string _name;

// Mapped to shadow property "Name" by convention that could be mapped by Automapper.

public string GetName() => _name; 

 

These are the common things in DDD you probably need to get used to when compared to tradditonal approach. Have fun coding !