Click “like” to see, form a habit, the public account search [dime technology] pay attention to more original technical articles. This article has been included in GitHub org_Hejianhui /JavaStudy.

preface

Recently, I joined a new team, and the overall framework direction is to build the business middle platform, delimit molecular domain, context, requirement structure and capability configuration. It is to divide the business middle platform’s domain on the whole through domain driving, and then divide the specific capability center of the business middle platform. At the beginning of this article, I will talk about the application of DDD (Domain-driven design) based on my own practical experience. Here we will focus on the following domain models that we often use: VO, DTO, DO, PO.

Entity classes in the domain model

The entity classes in the domain model can be divided into four models: VO, DTO, DO and PO. Each entity class is used for the interaction between different business levels, and the transformation between the entity classes will be realized within the levels.

The business layers are VIEW layer (VIEW+ACTION), SERVICE layer (SERVICE), and Persistence layer (DAO). The transfer of entities between the corresponding layers is as follows:

VO (View Object) View Object

A presentation layer that encapsulates all data for a given page (or component).

Data Transfer Object (DTO) Data Transfer Object

This concept comes from the J2EE design pattern. The original purpose is to provide coarse-grained data entities for the distributed application of EJB, so as to reduce the number of distributed calls, thereby improving the performance of distributed calls and reducing network load. But here, it is mainly used to show the data transfer objects between the layer and the service layer.

For example, if a table has 100 fields, the corresponding DTO has 100 attributes (in most cases, the data within the DTO comes from multiple tables). However, the View layer only needs to display 10 fields. Instead of passing the entire PO object to the client, we can use dtos with only 10 attributes to transfer data to the client without exposing the table structure on the server side. When it arrives at the client, if the object is displayed on the corresponding interface, its status changes to VO.

Domain Object (DO) Domain Object

Business entities, tangible or intangible, abstracted from the real world.

Persistent Object (PO) : Persistent Object

It maps one to one to the data structure of the persistence layer (usually a relational database), where each field in the data table corresponds to an attribute of the PO.

The understanding of the above concepts may not form an abstract thinking, so we use a sequence diagram to establish a model to describe the position of the above objects in the application of three-tier architecture:

  • The user submits a request (perhaps to fill out a form), and the form’s data is matched as VO at the presentation layer.
  • The service layer converts the VO to the DTOS required by the corresponding methods of the service layer and passes them to the service layer.
  • The service layer first constructs a DO (or rebuild) from the DATA of the DTO and invokes the business methods of the DO to complete the specific business.
  • The service layer converts the DO to the PO corresponding to the persistence layer (usually using ORM tools), invokes the persistence layer’s persistence method, passes the PO to it, and completes the persistence operation.

A reverse operation, such as reading data, is transformed and passed in a similar manner.

VO and DTO are compared

VO and DTO difference

At this point we might ask: why have a VO when a DTO is an object that passes data between the presentation layer and the service layer?

Yes, for the vast majority of application scenarios, DTO and VO attribute values are basically the same, and they are usually POJOs, so there is no need to bother. But don’t forget that this is the thinking of the implementation layer. For the design level, there should still be VO and DTO conceptually, so there are essential differences between the two. DTO represents the data that the service layer needs to receive and return, while VO represents the data that the presentation layer needs to display.

It might be easier to understand with an example:

For example, the Service layer has a getUser method that returns a system user with a property gender, which is only semantically defined for the Service layer: 1- male, 2- female, 0- not specified, while for the presentation layer, it may be necessary to use “handsome” for male, “beautiful” for female, and “secret” for not specified.

At this point, you might argue, in the service layer directly back to the “handsome, beautiful” isn’t it? This is not a problem for most applications, but it can become a problem if the requirements allow the client to customize the style and different clients have different requirements for the presentation layer. Furthermore, going back to the design level analysis, from the perspective of the single responsibility principle, the service layer is only responsible for the business and has nothing to do with the specific representation, so the Dtos it returns should not be coupled to the representation.

Theory to theory, this is still the level of analysis and design thinking, is it necessary to do so in the concrete implementation level? A one-size-fits-all approach often loses more than it gains, so here’s how to make the right choice in your application.

VO and DTO application

Just use a simple example above to say VO and DTO are different in concept, here we analyze concretely how to make the right choice in application.

In the following scenario, we can consider combining VO and DTO (note: implementation level) :

  • There is no need to distinguish BETWEEN VO and DTO when the requirements are very clear and stable, and the client is clear that there is only one client. VO can retire with one DTO. Why VO and not DTO? Going back to the design level, the responsibilities of the service layer should still not be coupled to the presentation layer, so you can easily understand from the previous example that dTOS still cannot use “hotties” for “gender” and that this transformation should rely on the page’s scripting (such as JavaScript) or other mechanisms (JSTL, EL, CSS).
  • Even if the client can be customized, or there are multiple different clients, VO can be made available if the client can implement the transformation using some technology (scripting or other mechanism)

Retreat.

The coexistence of VO and DTO is preferred in the following scenarios:

  • Consider defining VO at the implementation level for technical reasons, such as when a framework (such as Flex) provides automatic conversion of POJOs to fields in the UI. The trade-off is all about the development and maintenance efficiency gains from using the framework’s automatic transformation capabilities versus the reduction in development and maintenance efficiency that comes with designing one more VO.
  • If the page appear a “big view”, formed by the large view all the data you need to call multiple services, return multiple dtos to assemble (of course, this can also be through the service layer provides a one-time return a large view dtos to replace, but in the service layer to provide such a anticorrosion are appropriate, need to make a trade-off in design level).

Contrast DTO with DO

Difference between DTO and DO

First, there are conceptual differences. DTO is a data transfer object between the presentation layer and the service layer (think of it as a protocol between the two), while DO is an abstraction of various business roles in the real world, which leads to the data differences between the two.

For example: UserInfo and User, for a getUser method, it should never return the User’s password by nature, so UserInfo has at least one less password data than User. In domain-driven design, DO is not a simple POJO; it has domain business logic.

DTO and DO applications

From above it will reverse the problem: Since the UserInfo returned by getUser should not contain password, there should be no definition of password, but if there is also a createUser emsepsis, the passed UserInfo should contain the user’s password. How to do?

At the design level, the DTOS that the presentation layer passes to the service layer are conceptually different from the Dtos that the service layer returns to the presentation layer, but at the implementation level, we rarely do this (define two UserInfo, or more) because it’s not always wise to do so. We can design a fully compatible DTO. In the service layer receives data, should not be set by showing layer properties (such as a sign of the order should be decided by the unit price, quantity, discount, etc), whether display layer Settings, the service layer without any oversight, and returned to the data in the service layer, shouldn’t the data returned (e.g., the user password), don’t set the corresponding properties.

In the case of DO, one more thing: why not just return DO in the service layer? In this way, DTO coding and conversion work can be saved for the following reasons:

  • The essential difference between the two may lead to that they DO not correspond to each other one by one. A DTO may correspond to multiple DOS, and vice versa, and even there is a many-to-many relationship between the two.
  • DO has some data that should not be known to the presentation layer;
  • DO have business method, if the DO directly passed to display layer, presentation layer code can bypass the service layer directly call it should not access operation, based on AOP interception service layer to access control mechanism, this problem is particularly prominent, and in the show layer calls DO business method may also be because the problem of things, Make things hard to control.
  • Some ORM frameworks (like Hibernate) often use “lazy loading” techniques. If you expose DO directly to the presentation layer, for the most part the presentation layer is out of the realm of things (Open session in View is not a desirable design in most cases). Session before the close of the case if the try to obtain a did not load the associated objects, there will be a runtime exception (for Hibernate is LazyInitliaztionException);
  • At the design level, the presentation layer depends on the service layer, and the service layer depends on the domain layer. If YOU expose DO, the presentation layer directly depends on the domain layer. This is still a one-way dependency, but this cross-layer dependency leads to unnecessary coupling.

For DTOS, it must also be explained that A DTO should be a “flat two-dimensional object”. For example:

  • If User is associated with several other entities (such as Address, Account, Region, and so on), does the UserInfo returned by getUser() need to return the Dtos of all the objects it is associated with? If this is the case, it will inevitably lead to a large amount of data transfer, which is unacceptable for distributed applications because it involves data transfer, serialization, and deserialization over the network.
  • If getUser needs to return an AccountId, AccountName, RegionId, and RegionName in addition to the basic User information, define these attributes in UserInfo. Squish a “solid” object tree into a “flat two-dimensional object”.

DO versus PO

Difference between DO and PO

For the most part, DO and PO correspond one to one. PO is a POJO with only get/set methods, but there are some scenarios that reflect fundamental conceptual differences between the two:

  • DO in certain situations DO not require explicit persistence, such as using the strategy pattern design of goods discount policy, can derive discount strategy interfaces and different discount strategy implementation class, these discount strategy implementation class can DO, but they will only resides in the static memory pool, DO not need to be persisted to the persistence layer, therefore, There is no corresponding PO for this kind of DO.
  • For example, there is a many-to-many relationship between Teacher and Student. In the relational database, this relationship needs to be represented as an intermediate table, which means that there should be a TeacherAndStudentPO. However, this PO has no practical significance in the business field, and it cannot correspond to any DO at all.

Not all many-to-many relationships DO not have business implications. This is related to specific business scenarios. For example, the relationship between two pos affects the specific business, and there are many types of such relationships. There is a many-to-many relationship between “roles” and “resources”, and this relationship is clearly represented as a DO — “permissions”.

In some cases, one PO may correspond to multiple DOS for persistence or performance reasons, and vice versa. For example, the Customer has contact information Contacts. There are two one-to-one DO’s, but perhaps for performance reasons (in extreme cases, for example), the Customer and Contacts DO data are merged into a single table to reduce connection queries in the database. On the other hand, if a Book, Book, has a property called cover, but that property is the binary data of an image, and some query operations do not want to load cover at all, thus reducing disk I/O overhead, and assuming that the ORM framework does not support attribute-level lazy loading, Then you need to consider separating the cover into a data table, so that a DO corresponds to multiple pos. Some PO attribute values have no meaning for DO. These attribute values may be data that exists to resolve some persistence strategy. For example, to implement “optimistic locking”, PO has a version attribute that has no business meaning for DO and should not exist in DO. Similarly, there may be properties in DO that DO not require persistence.

Application of DO and PO

Since the ORM framework is very powerful and popular, and JavaEE also launched the JPA specification, the current business application development basically does not need to distinguish DO and PO, PO can be completely hidden in DO through JPA, Hibernate Annotations/ HBM. Nevertheless, there are some issues that we must pay attention to:

  • Properties that DO not require persistence need to be explicitly declared by ORM, such as @TRANSIENT declaration in JPA.
  • For a PO attribute that exists for a persistence policy, such as version, the attribute must be declared in DO because DO and PO are merged. However, since this attribute has no business significance for DO, it needs to be hidden from the public. The most common approach is to privatize the get/set method of this attribute. It doesn’t even provide get/set methods. For Hibernate, however, this is especially important because Hibernate uses reflection to create a DO instance by calling the empty parameter constructor of DO and then using JavaBean specifications to reflect the set method to set the value for each attribute. If you DO not explicitly declare the set method, or if you make the set method private, Hibernate will not be able to initialize DO, resulting in a runtime exception. It is possible to make the property’s set method protected.
  • Hibernate provides good support for scenarios where one DO corresponds to multiple pos, or one PO corresponds to multiple DOS, as well as attribute level lazy loading (see Hibnate’s resources).

conclusion

So far, I have clearly understood the concepts, differences and practical applications of VO, DTO, DO and PO. Through the detailed analysis above, we can also conclude a principle: Analysis and design level and implementation level is the level of two independent, even if the implementation level by some technical means can put two completely independent concepts close 2 for one, based on the analysis of the design level, we still (at least) in your mind needs to distinguish conceptually independent things clear, this principle is important for to do analysis and design (tool is more advanced, Tends to make us more numb).

GitHub Org_Hejianhui /JavaStudy GitHub Hejianhui /JavaStudy