ABP plus DDD development: low coupling, reusable and extensible work order business module – Introduction and integration

Time:2021-4-29

preface

Many scenarios [monomer + modularization] are more suitable than microservices, with low development difficulty, strong code reusability and scalability. There are some difficulties in modular development, such as module startup and unloading, dependence and communication between modules. asp.net core  abpIt provides us with the ability of modular development and other basic functions. be based onabp(Gen 6.3) combined with DDD, a work order management module has been basically developed. This article gives a basic introduction and explains how to integrate this module.

resources

Video Explanation:https://www.bilibili.com/video/BV1ky4y1b79u/

Online demo:http://web1.cqyuzuji.com:9000/   Account number: admin Password: 123qwe

Back end source code:https://gitee.com/bxjg1987/abp

Front end source code:https://gitee.com/bxjg1987/front

Essential knowledge

Familiar with asp.net core and ABP

term

Here are some concepts that are important to understand.

ABP module: This is not explained, it is the basis of ABP, please refer toOfficial documents

General module: This is to use the ABP module development method to do some general, business independent modules, such as: data dictionary module

Business module: work order management, advertising management, e-commerce module, in order to achieve specific business modules.

Business scenarios

The customer rents the copier. He wants to manage the whole business with a system. The work order is an important module. The process is as follows:

  1. Customers through the small programReportWork order, indicating what is wrong with the equipment
  2. After the system background administrator looks at the general problemto examine    
  3. The background administrator will check the approved work orderdistributionTo designated maintenance personnel, or maintenance personnel through the app itselfreceiveApproved work orders
  4. When the maintenance personnel arrive at the customer, the work order is set to finished through the appimplementstate
  5. When the maintenance personnel finish processing the task, they can set the work order to finished through the appcompleteAt the same time, you may need to enter the completion description

The above is the main process, and there are still some corners that will be explained in detail in the future, such as: jumping from the audit state to the completed state; Return from completed status to pending status; Events when the state changes, etc.

Different types of work orders: some work orders may not be submitted by customers. For example, when the purchased second-hand equipment needs to be repaired when it is put into storage, work orders will also be generated. In this case, work orders will not be associated with customers, but will be associated with stock in orders; Another example is to ask an employee to come back by express. In this case, the work order will be associated with logistics information

There are different ways to create a work order: the customer submits it through a small program, the background administrator creates it manually, and it is automatically created when certain events occur (for example, it is automatically created when purchasing stock in)

In fact, the work order management module is a general business, which may be needed in many systems. Therefore, it is considered to make an independent business module to facilitate reuse.

target

Reusable

The work order module is released in nuget package. You can install it and use it after simple configuration.

Easy to upgrade

As mentioned above, the nuget package will be released in the form of nuget package, and a new version of nuget package will be released after the module is updated in the future. When the system is updated, it is OK to refer to the new version of nuget package

Independence

The work order module only depends on some general and non business modules. The work order module needs to use the concept of “employee”, which is often reflected as a user in the system. The work order module itself does not provide the function of “employee management”, because your system may have its own “employee management” function; Or you can take the original abpuser of ABP as an employee. Imagine that if the “work order module” itself provides an employee management module, you can refer to the past and find that you have implemented employee management in your system, isn’t it very troublesome?

So when your project references the work order module, you need to make an adaptation to provide employee related functions for the work order module, mainly several queries.

explain:

ABP vNext uses the contract layer to realize module independence. I think it is incomplete. For example, there is an “employee management” module in your project. When you define the contract interface and dto, you can only define the common one. In order to be as common as possible, there will be as many methods in the interface, or separate multiple interfaces, and there will be as many attributes in dto, Because you don’t know which modules will refer to you in the future, you can’t define accurate and just enough interfaces and DTOs.

Now there are “salary management” modules. If you refer to your “employee management module”, it will get many unnecessary attributes in dto and many unnecessary methods when introducing interfaces.

Another example is my “work order module”. If I directly refer to your contract, I will release the work order module in the future. After other systems refer to it, it must implement the interface in the “employee contract”. It will be very confused. Do I want to implement all the interfaces in this contract? Do I need to assign values to all dto properties? In fact, the interface method work order module in some contracts may not be needed at all, and the dto in contracts may not all need assignment.

There are more problems. These problems do not affect the use, but they are very awkward. The reason for this is that an independent business module should define in the contract what data it can provide,You should also define what you need, rather than let the contracts of other modules specify it

When we develop the work order module, we will define the contract from these two directions: what data does the work order module need? What data can the work order module provide?

Scalable

ABP itself provides strong scalability, you can

  1. Extending entity class by “dynamic attribute system”
  2. Add your own business logic through work order crud, work order status change and other events
  3. By integrating and replacing the work order module, domain services and application services are provided to rewrite the existing business logic
  4. The default UI is only implemented with easyUI in combination with my own project. You can implement your own UI
  5. More work order types can be realized by integrating abstract work order entities, abstract work order domain services and abstract work order application services

Using DDD development mode

DDD in practice

The core business logic is in the work order entity class, which defines the corresponding business methods. Some internal states of the work order entity will be changed, and corresponding events will be triggered when necessary, so as to ensure that the work order can always be in the correct state. For example, a completed work order has no associated employees or has no start and finish time; Another example is a rejected work order. There is no rejection description. If the attributes of the entity are all public get; set; It’s easy to have this kind of problem, because in collaborative development, others are likely to call your entity randomly and set values at will.

Domain service has a small amount of code, which also triggers corresponding domain events.

Application services receive front-end calls and coordinate domain entities and services to realize business logic.

About DDD, I’ll talk about it in detail when I explain the design idea in the next chapter

integrate

In scalability, it is mentioned that the work order is abstract, but it provides an implementation of “ordinary work order” by default, so this function is available immediately after installing and configuring the module. In addition, you can also provide several subclasses to implement a custom type work order.

Online demo:http://web1.cqyuzuji.com:9000/  Account number: admin Password: 123qwe

First, download a clean ABP project from the ABP official, and use abp6.3. Net 5 when writing this article. Or you can introduce and test it in your current project. Follow these steps to configure.

Install nuget package

Related nuget packages are prefixed with: bxjg. Workorder.

Make sure that:

Right click on Solutions > Manage packages for Solutions > Update – >   Upgrade castle.windsor.ms dependency injection to 3.4.0

Right click on Solutions > Manage packages for Solutions > Update – >   Update microsoft.entityframeworkcore to 5.0.4

30. In the core layer

Install-Package BXJG.WorkOrder.EFCore -Version 1.0.0-rc3

30. In the entityframework core layer

Install-Package BXJG.WorkOrder.EFCore -Version 1.0.0-rc3

30. In the application layer

Install-Package BXJG.WorkOrder.Application -Version 1.0.0-rc3
Install-Package BXJG.WorkOrder.EmployeeApplication -Version 1.0.0-rc3

In the work order module, the background management work order and employee end-to-end work order operations are defined by two separate application layer projects. You can decide whether to separate them according to your situation. If they are separated, the above packages need to be installed separately.

to configure

Register related entities in dbcontext

Since the work order module does not use the independent dbcontext, you need to register and configure the entities of “ordinary work order” and “work order classification” in the dbcontext of your main program. Find your dbcontext in the XXX. Entityframeworkcore layer and configure it as follows:

1         public virtual DbSet BXJGWorkOrderCategory { get; set; }
2         public virtual DbSet BXJGWorkOrder { get; set; }
3 
4         protected override void OnModelCreating(ModelBuilder modelBuilder)
5         {
6             base.OnModelCreating(modelBuilder);
7             modelBuilder.ApplyConfigurationBXJGWorkOrder();// Don't forget the mapping configuration here
8         }

Register permissions and menus

The general job order management and the employee side related permissions have been defined as extension methods, which can be called directly in the main program and registered to the permission tree of the main program. Register the permissions of [ordinary work order] and [work order classification] in xxx.core/authorization/xxxauthorization provider. For demonstration, the permissions are registered under the tenant permissions.

admin.AddBXJGWorkOrderAllPermission();

Similarly, register the menu of general work order and work order classification in bxjg.web.mvc/startup/xxxnavigationprovider

context.Manager.MainMenu.AddBXJGWorkOrderAllNav();

By default, the root of the work order module, the work order classification, the permission and menu of the default work order will be registered. You can call several other extension methods with similar names to register the required permission and menu respectively. You can also define the registration of the permission and menu by ABP. In this case, if you want to use the function of the default work order, the name of the permission must correspond, Please refer toDefault work order permission constant name

Register dynamic API

Because it is not sure how you will use the application layer of the work order module when developing the module, it is not automatically registered as a dynamic web API by default. If you need to configure it yourself, it is manual at present, and the extension method may be provided for one-time registration in the future. In preinitialize() of xxx.web.core/xxxwebcoremodule, configure and enable the related dynamic web API of common work order and work order classification in work order module

1 // register the dynamic API configuration. Modules. Abpaspnetcore(). Createcontrollers for app services (type of (bxjg. Workorder. Applicationmodule). Assembly, "bxjgworkorder");
2 // register the dynamic API configuration. Modules. Abpaspnetcore(). Createcontrollers for app services (type of (bxjg. Workorder. Bxjgcommonapplicationmodule). Assembly, "bxjgworkorder") for managing work orders in the background and employee side;
3 // register the dynamic API configuration. Modules. Abpaspnetcore(). Createcontrollers for app services (type of (bxjg. Workorder. Bxjgworkorder, employeeapplicationmodule). Assembly, "bxjgworkorder");

Add module dependency

Although the module related package references have been added, these packages are just ordinary DLLs for the main program at this time. The module of the main program must depend on the work order module in ABP mode, so that the DLL in the work order module can be started in ABP mode. Since the work order module is only provided to the application level, it is most appropriate to add dependencies to the module class in the application layer of the main program. Add module dependency in xxx.application/xxxapplicationmodule

[dependson]
               typeof(BXJG.WorkOrder.ApplicationModule),                             typeof(BXJG.WorkOrder.BXJGWorkOrderEmployeeApplicationModule))]
    public class XXXApplicationModule : AbpModule
    {

Add module adaptation code

As mentioned above, the dependence of the work order module on employees is isolated through the iemployeeappservice interface. By default, abpuser is regarded as an employee, but your user type cannot be determined when designing the module. Therefore, you need to register the service in your main program xxapplicationmodule. Initialize() as follows

IocManager.RegisterBXJGWorkOrderDefaultAdapter();// User is the user type of your project

Of course, this service can be replaced.

In addition, the employee end-to-work order management service needs to obtain the currently logged in employee, so the iemployeesession interface is specified. The iabpsession provided by ABP is used by default. No configuration is required for this. Of course, you can also replace this service

Database migration

This is according to the ABP routine, which will not be detailed. Note that the connection string of the project downloaded from ABP is connected to localhost by default, while the localdb of vs2019 is slightly different. I’ll change it to the following form. You can do as you like

"Default": "Server=(localDB)\mssqllocaldb; Database=BXJGDB; Trusted_Connection=True;"

function

If there is no accident, the interface can be accessed

  

  • Workorder: the interface for the background administrator to manage the work order. Changestatus is to jump or back the work order to the specified state. This operation is not in place in one step. For example, from the “to be approved” state to “completed” state, there will be steps such as confirmation, assignment, execution, completion, etc. the operator must have the authority for these steps, The status of the work order must be correct (for example, whether the work order has been associated with a handler will be judged during allocation. It is only assumed that this restriction is not made at present). Most of this logic is in the work order entity.
  • Workordercategory: the interface for the background administrator to maintain the work order classification
  • Workordercommon: an interface that can be called by either the employee side or the background management side to obtain the work order status list, urgency list, etc
  • Workorderemployee: the interface for the employee to operate the work order, such as obtaining, executing and completing the work order to be assigned.

follow-up

  • At present, the real independent business module has been realized
  • The configuration needs to be further simplified
  • At present, it can basically run through the work order process without detailed test.
  • The above describes the basic integration of the module and the function of “ordinary work order” implemented by default in the module. How to extend it will be explained later, for example, how to implement a work order of user-defined type, how to extend the work order module through inheritance, events, etc.
  • At present, the module only provides the application layer level, that is, only provides the back-end interface. The easyUI I use in the front-end can use ABP’s virtual file system to realize UI modularization, but at present, it does not. You can use your favorite framework to complete UI