Concept:

VO (View Object) : A View Object used in the presentation layer to encapsulate all data for a given page (or component).

DTO: Data transfer objects, this concept is derived from the J2EE design patterns, the original purpose is to provide coarse-grained distributed applications of EJB data entities, to reduce the number of distributed call, so as to improve the performance of distributed call and reduce the network load, but here, I refer to display data transfer objects between the layer and service layer.

DO (Domain Object) : A Domain Object is a tangible or intangible business entity abstracted from the real world.

Persistent Object (PO) : A Persistent Object that forms a one-to-one mapping relationship with the data structure of the persistence layer (usually a relational database). If the persistence layer is a relational database, each field (or several fields) in the data table corresponds to one (or several) attributes of PO.

Model:

The following is a simple model using a sequence diagram to describe the position of the above objects in a three-tier architecture applicationCopy the code

L The user makes a request (perhaps to fill out a form), and the form’s data is matched as VO at the presentation layer.

L The presentation layer converts VO to the DTOS required by the corresponding methods of the service layer and sends them to the service layer.

L The service layer first constructs (or reconstructs) a DO based on the data of the DTO, and calls the business methods of the DO to complete the specific business.

L The service layer converts the DO to the corresponding PO of the persistence layer (either using ORM tools or not), calls the persistence layer’s persistence method, passes the PO to it, and completes the persistence operation.

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

VO and DTO difference

One question you might ask (and many programmers on my project have the same question) is: why do you need a VO when a DTO is the object that passes data between the presentation layer and the service layer? Right! For most application scenarios, the attribute values of DTO and VO are basically the same, and they are usually POJOs, so there is no need to bother, but don't forget that this is the implementation level of thinking, for the design level, there should be VO and DTO conceptually, because they are fundamentally different. 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. An example might be easier to understand: 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- unspecified, while for the presentation layer, it may need to use "handsome" for male, "beautiful" for female, and "secret" for unspecified. At this point, you might argue, why not just go back to "hotties" on the service level? For most applications, it is not a problem, but imagine, if demand to allow customers can customize the style, and different style for the "gender" doesn't show up the same way, or the service at the same time for the use of multiple clients (different portal), and different client is different to the requirement of the presentation layer, so the problem comes. Furthermore, going back to the design level, 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. Therefore, the DTOS it returns should not be coupled with the representation. Theory to theory, this is the level of analysis and design thinking, is it necessary to do so in the implementation level? A one-size-fits-all approach is often counterproductive, and I'll look at how to make the right choice in an application in a moment.Copy the code

VO and DTO application

This section will show you how to make the right choice in your application. In the following scenarios, we can consider combining VO and DTO as one (note: implementation level) :Copy the code

L When the requirement is very clear and stable, and the client is clear that there is only one, there is no need to distinguish VO and DTO, VO can retire, just use a 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, as you can easily understand from the previous example, the DTO for “gender” still cannot use “handsome and beautiful”, and this transformation should rely on the page’s scripting (such as JavaScript) or other mechanisms (JSTL, EL, CSS).

L Even if the client can be customized, or there are multiple different clients, VO can be retired if the client can implement the transformation using some technology (scripting or other mechanism)

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

L The opposite of the above scenario

For technical reasons, such as when a framework (such as Flex) provides automatic conversion of POJOs to UI fields, consider defining VO at the implementation level. 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.

L if page appears 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 method is appropriate, need to make a trade-off in design level).

Difference between DTO and DO

The first is the conceptual difference. DTO is the data transfer object between the presentation layer and the service layer (think of it as the protocol between the two), while DO is the abstraction of various business roles in the real world. This leads to the data difference between the two, such as UserInfo and User (for the naming rules of DTO and DO, For a getUser method, it should never return the User's password per se, so UserInfo has at least one less password data than User. In domain-driven design, as the first article in the series explained, DO is not a simple POJO, it has domain-driven business logic.Copy the code

DTO and DO applications

From the examples in the previous section, careful readers may find problems: Since the UserInfo returned by getUser should not contain password, there should be no definition of password, but what if there is also a createUser method and the UserInfo passed in needs to contain the user's password? 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 order price should be decided by the unit price, quantity, discount, etc), whether display layer, service layer without any oversight, and returned to the data in the service layer, shouldn't the returned data (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:Copy the code

L 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, or even there is a many-to-many relationship between the two.

L DO has some data that should not be known to the presentation layer

L DO with a business method, if the DO directly passed to the presentation 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, the problem is particularly prominent, and in the show layer calls DO business method may also be because the problem of transaction, transaction is difficult to control.

For some ORM frameworks such as Hibernate, “lazy loading” is often used. If you expose DO directly to the presentation layer, for the most part the presentation layer is not within the scope of the transaction (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 LazyInitiliaztionException).

L From the design level, the presentation layer depends on the service layer, and the service layer depends on the domain layer. If DO is exposed, the presentation layer will directly depend on the domain layer. Although this is still a one-way dependence, such cross-layer dependence will lead to unnecessary coupling.

For DTOS, there is also a point that must be explained, that is, 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. A “three-dimensional” object tree is “flattened” into a “flat two-dimensional object”. The project the author is currently involved in is a distributed system, which converts all related objects of an object into a DTO object tree with the same structure and returns it, resulting in very slow performance.

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:Copy the code

L 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 only resides in the static memory, don’t need to be persisted to the persistence layer, therefore, there is no such DO the corresponding PO.

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”.

L In some cases, a PO may correspond to multiple DOS, and vice versa, for persistence or performance reasons. 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 there is a DO pair for each PO.

L Certain 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:Copy the code

L For attributes that DO not require persistence, they need to be explicitly declared by ORM, such as @TRANSIENT declaration in JPA.

L For attributes in PO that exist for a persistence policy, such as version, DO and PO are merged and must be declared in DO. 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, but for Hibernate, this is especially important because Hibernate uses reflection to call DO’s empty argument constructor to construct the DO instance. The JavaBean specification then reflects the set method to set the value for each attribute. If you DO not explicitly declare the set method, or 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 documentation).