The first wave of DDD actual combat advanced (four): develop a direct sales system for the general business of the big health industry (build a lightweight framework that supports DDD three)

In the previous article, we talked about the advantages of the classic DDD architecture compared to the traditional three-tier architecture, and the responsibilities of each layer of the classic DDD architecture. This article will introduce the main code of the lightweight framework that supports DDD in the infrastructure layer.

What needs to be explained here is that the DDD lightweight framework can embody the idea of ​​DDD.

1. Top-level representations of entities, aggregate roots, and value objects

Entity top-level definition:

 public  interface IEntity
    {
        string Code { get; set; }
        Guid Id { get; set; }
    }

Id is a technical primary key that will be stored in the database table in the future, and Code is the unique business identifier of the domain object. You can also extend this interface and define two entity comparison interfaces (the future implementation is to compare two entities if the Code is the same, it means that the two entities are equal).

Aggregate root top-level definition: 

 public  interface IAggregationRoot:IEntity
    {

    }

The aggregate root interface is inherited from the entity interface, but the future usage can be defined in the repository. The persistent domain object must be inherited from this interface or an abstract class that inherits this interface.

Value object top-level definition:

 public interface IValueObject
    {
        Guid Id { get; set; }
    }

The value object interface only needs to keep a technical primary key, it has no business identifier. In a database, value objects may be stored as separate tables or as part of an entity. You can also extend this interface to define two value object comparison interfaces (future implementations

It is to compare two value objects, if all property values ​​are the same, it means that the two value objects are equal).

Work unit top-level definition:

public  interface IUnitOfWork
    {
        void Commit();
    }

The unit of work interface defines a commit method, which is actually the transaction commit method of the entire aggregate of the corresponding EF Core when it is implemented.

Repository interface top-level definition:

public interface IRepository:IUnitOfWork,IDisposable
    {
    }

The repository interface inherits from the unit of work interface and the resource release interface, providing top-level constraints for future data access frameworks and replaceability.

EF Core top-level repository persistence implementation:

public class EFCoreRepository : IRepository
    {
        private readonly DbContext context;
        public EFCoreRepository(DbContext context)
        {
            this.context = context;
        }
        public void Commit()
        {
            try
            {
                context.SaveChanges();
            }
            catch(Exception error)
            {
                throw error;
            }
        }

        public  void Dispose()
        {
            context.Dispose();
        }
    }

As can be seen from the above code, the Commit method that mainly implements the repository interface is actually using the SaveChanges() transaction commit method of the DbContext data access context class of EF Core, and the use case of the application service layer can obtain an aggregate root , and then call the Commit method of the repository interface, which implements a one-time transaction commit of all objects in the aggregate.

 

2. Implementation of common tool classes

We should also define another project, which is a tool that the entire system needs to use, which should at least include the reading of Asp.net Core Json configuration files, Json serialization and deserialization, encryption, dependency injection, and return to the front end The object format definition, etc., here

List a few that are needed first, and others will be added in specific cases later.

Asp.net Core Json configuration file reads:

The Json configuration file will store some of our configuration information, such as the database connection string, WeChat AppId and AppSecure, etc., so it needs to have a function to support the reading of the Key to Value of the Json configuration file

public class AppSetting
    {
        private  static IConfigurationSection appsections = null ;
        public  static  void SetAppSetting (IConfigurationSection section)
        {
            appsections = section;
        }
        public static string GetAppSetting(string key)
        {
            string str = "";
            if (appsections.GetSection(key) != null)
            {
                str = appsections.GetSection(key).Value;
            }
            return str;
        }
    }

Returns the object format definition of the front end:

Our application service layer will return a certain data format of the WebApi interface, and the WebApi interface will also return this data to the front end, and the front end will do the corresponding processing after getting it.

 public class ResultEntity<T>
    {
        public bool IsSuccess { get; set; }
        public string Msg { get; set; }
        public T Data { get; set; }
        public int ErrorCode { get; set; }
        public int Count { get; set; }
    }
public class BaseAppSrv
    {
        protected ResultEntity<T> GetResultEntity<T>(T vobj, string msg= " Failed to get the object " , int errorcode = 0 )
        {
            var ueresult = new ResultEntity<T>();
            var issuccess = true;
            if(vobj is int && Convert.ToInt32(vobj) <= 0)
            {
                issuccess = false;
            }
            else if(vobj is bool && !Convert.ToBoolean(vobj))
            {
                issuccess = false;
            }
            else if(vobj is string && string.IsNullOrEmpty(Convert.ToString(vobj)))
            {
                issuccess = false;
            }
            if (!issuccess)
            {
                ueresult.Msg = msg;
                ueresult.ErrorCode = 200 ;
            }
            ueresult.IsSuccess = issuccess;
            ueresult.Data = vobj;
            return ueresult;
        }
    }

All future use cases will be inherited from BaseAppSrv, and the final returned format will be ResultEntity<T>.

Well, the basic framework is set up. In the next chapter, you can directly enter the case to see how to design through DDD thinking in the case, and write the code of the actual business system through the classic DDD architecture and DDD lightweight framework.

 

QQ discussion group: 309287205 

Please pay attention to the WeChat public account for the advanced video of DDD actual combat:

 

Guess you like

Origin http://43.154.161.224:23101/article/api/json?id=324499861&siteId=291194637
ddd
Recommended