ABP Modules and Entity Dependencies

8/11/2023 8:40:04 PM

Intro

This post discusses how one typically handles cross-module dependencies.

Personal preferences will be incorporated into this post.

As there is often confusion, especially in the field of module development, I wanted to take this opportunity to share some information.

In the future, we will delve deeper into module development, provide content on development with ABP, and also introduce our own modules.

Originally, the plan was to explicitly address module implementation with best practices, demonstrate various approaches on module consumption and data consistency, and provide as many resources as possible here. Unfortunately, this became a bit overwhelming. As a result, we decided to start small for now.

This marks the beginning of a series of posts. We aim to first provide a basic understanding of how we interpret modules and then address the posed question.

Description

A brief recap for clarification. So, what exactly are ABP modules?

First and foremost, a module is a highly encapsulated piece of software that developers can use in their ABP applications to access specific functionalities.

When we want to send emails, there is a module that explicitly provides this functionality. When we need CMS functionalities (blogs, pages, comments, etc.), there is also a module for that - the CMS Kit. As seen from the examples, modules can vary in size, from being quite small to very extensive.

We generally categorize modules into two distinct categories, as defined here:

Framework modules: These are core modules of the framework, such as caching, emailing, theming, security, serialization, validation, EF Core integration, MongoDB integration, etc. They do not contain application/business functionalities but make your daily development easier by providing common infrastructure, integration, and abstractions.

Application modules: These modules implement specific application/business functionalities, such as blogging, document management, identity management, tenant management, etc. They generally have their own entities, services, APIs, and UI components.

So, there are Framework and Application modules. The key difference lies in the level of generalization/domain independence of a module. Thus, it is legitimate for the CMS Kit (Application) to rely on or reference the Mailing module (Framework), even if modules themselves should not be aware of each other.

Module Benefits/Disadvantages

The main reasons for developing a module are reusability and isolation.

The main reasons against developing a module are, on one hand, the initial overhead and, on the other hand, complexity.

Use Case

Let's consider the following highly simplified scenario (without evaluating the meaningfulness):

Two modules are to be developed:

  • Module A: Customer Management. Entities: Customer, Country
  • Module B: Project Management. Entities: Project, Customer

These modules will be consumed by an ABP application. The special requirement is:

We want that when a customer is created in Module A, the same customer is also present in Module B. And vice versa. They should be synchronized.

No-Go

The following should be noted at this point. What you definitely need to avoid are constructions like this:

"I am developing an application in which customers and projects exist. It would be a good idea to write modules for them and structure them as follows:

  • Module A: Customer Management. Entities: Customer, Country
  • Module B: Project Management. Entities: Project

And in the consuming application, the Customer Management (Module A) needs to be aware of the existence of projects, and the Project Management needs to be aware of the existence of customers. Later, in my application, I just have to install the modules, and everything will work."

Why is this a no-go? Because we are writing modules that do not function independently. We already know before implementation that there are co-dependencies. If we later want to use the Project Management module in another project, problems will arise.

Remember:

Modules must function sensibly in isolation and exhibit maximum reusability!

Application modules have no knowledge of each other!

Implementation

So, how do we go about the initial setup?

As always, there are multiple ways to reach the goal. There's no single truth or preferred approach here. Cross-module dependencies should naturally be avoided, but in practice, that's not always possible.

In the most basic approach, the entities are duplicated by the consuming application.

This process can be easily achieved using the Entity Synchronizer.

Every time a customer is edited in Module A or B, we intercept this and incorporate the changes into the other module to keep them synchronized. We can do that, because the consuming application knows both modules and is able to communicate between them. This inevitably leads to data redundancy, but it often is the simplest way to maintain consistent data.

To provide an example, we've written a very simple repository.

https://github.com/Chrobyte/abp-module-sync

To keep things simple, we reduced everything to the bare minimum. We did not follow any best practices (did not even do translation, no DDD no nothing). But hopefully this is of good reference for you to see how things may be wired up together.

Please follow the Commit History to see the different steps.

Closing Remarks

In future module-specific posts, we will reference this article as a foundation and provide information on how we implement modules for maximum reusability along with more realistic examples :)

Our posts will be uploaded on our website and in the ABP Community.

If you find our content interesting, feel free to subscribe to our newsletter.

Additional Resources

Last Modification : 8/12/2023 12:22:36 PM


abp

Cookies

This site uses cookies.
This website uses cookies. Some cookies are technically necessary, others are used to analyze user behavior in order to optimize the offer. You can find an explanation in our Privacy Policy.