Original address: http://www.blogjava.net/johnnylzb/archive/2010/05/27/321968.html
The previous article as a primer, explained the advantages of domain-driven design, from this article, the author will be combined with their own practical experience, talk about the application of domain-driven design. This article focuses on some of the objects we will often use: VO, DTO, do, and PO.
Since different projects and developers have different naming conventions, here I begin with a simple description of the above concepts, the name is just a logo, we focus on its concept:
Concept:
VO (View Object ): The View object, used for the presentation layer, that encapsulates all the data for a specified page (or component).
DTO (Data Transfer Object ): Data Transfer object, this concept is derived from the design pattern of the Java EE, the original purpose is to provide a coarse-grained data entity for the distributed application of EJB, to reduce the number of distributed calls, thus improve the performance of distributed calls and reduce the network load, but here, I refer to the data transfer object between the presentation layer and the service layer.
Do (Domain Object ): domain objects are tangible or intangible business entities that are abstracted from the real world.
PO (Persistent Object ): a persisted object that forms a one by one mapping relationship to the data structure of the persistence layer (usually the relational database), and if the persistence layer is a relational database, then each field (or several) in the data table corresponds to one (or several) attributes of the PO.
Model:
The following is a sequence diagram that establishes a simple model to describe the location of the above objects in a three-tier architecture application
The user makes a request (possibly filling out a form), and the data of the form is matched to VO in the presentation layer.
The display layer converts VO to the DTO required by the service layer correspondence method and transmits it to the service layer.
The service layer first constructs (or rebuilds) a do based on the data of the DTO, invoking the Do business method to complete the specific business.
The service layer converts do to the PO that corresponds to the persistence layer (you can use the ORM tool or not), calls the persistence method of the persistent layer, passes the PO to it, and completes the persistence operation.
L for a reverse operation, such as reading data, is also converted and passed in a similar way, slightly.
VO with DTOs the Difference
You may have a question (many programmers have the same doubts in the project I'm involved in): Since DTOs are the objects that pass data between the presentation layer and the service layer, why do we need a VO? Right! For most scenarios, dto and VO attribute values are basically consistent, and they are usually pojo, so there is no need to superfluous, but do not forget that this is the implementation level of thinking, for the design level, there should be the concept of VO and DTOs, because the two have an essential difference, A DTO represents the data that the service layer needs to receive and the data returned, and VO represents the data that the presentation layer needs to display.
An example of this might be easier to understand: for example, the service layer has a GetUser method that returns a system user with a property of gender (gender), which is semantically defined for the service layer: 1-male, 2-female, 0-unspecified, and for the presentation layer, It may need to be "handsome" on behalf of men, with "beauty" on behalf of women, with "secret" representative unspecified. Speaking of which, perhaps you will also refute, in the service layer directly back to "handsome" is not OK? This is not a problem for most applications, but imagine that if the requirements allow customers to customize the style, and the different styles do not behave differently for "gender", or if the service is used by multiple clients (different portals), and different clients have differing requirements for the performance layer, then the problem comes. Furthermore, back to the design level, from a single principle of responsibility, the service layer is only responsible for the business, independent of the specific manifestation, therefore, the DTO that it returns should not appear coupled with the form of expression.
Theory to the theory, this is the analysis of the design level of thinking, whether in the implementation level must do so? One-size-fits-all approach tends to outweigh the gains, and I'll immediately analyze how to make the right choices in the app.
VO with DTOs the application
The above only uses a simple example to illustrate the conceptual difference between VO and dto, and this section will show you how to make the right choice in your application.
In the following scenario, we can consider the VO and the Dto two to one (note: is the implementation level):
L When the demand is very clear and stable, and the client is very clear only one time, there is no need to distinguish between VO and dto, when VO can retire, with a dto can, why Vo retired rather than DTOs? Back to the design level, the responsibility of the service layer should still not be coupled with the presentation layer, so, for the previous example, you can easily understand that DTOs for "gender", still can't use "handsome", this conversion should rely on the page script (such as JavaScript) or other mechanisms (JSTL, EL, CSS)
L Even if the client can be customized, or there are many different clients, if the client can use some technology (script or other mechanism) to achieve the conversion, can also let Vo retire
The following scenarios need to prioritize VO and dto coexistence:
L The reverse scene of the above scene
For some technical reasons, such as a framework such as Flex, which provides the ability to automatically convert Pojo to some field in the UI, consider defining VO at the implementation level, This tradeoff is entirely dependent on the comparison between the development and maintenance efficiencies brought about by the use of the framework's automatic conversion capability and the increased efficiency of the development and maintainability of the design more than what VO does.
L If a "big view" appears on the page, and all the data that makes up this large view needs to call multiple services and return multiple DTOs to assemble (of course, this can also be replaced by a dto that returns a large view at the service layer, but it is appropriate to provide a method at the service layer, Needs to be weighed at the design level).
DTO and do the Difference
The first is the conceptual distinction, where dtos are data transfer objects between the presentation layer and the service layer (which can be considered an agreement between the two), and do is an abstraction of the various business roles in the real world, which leads to the difference in data between the two. For example, UserInfo and user (for DTOs and do naming conventions, see the author's previous blog post), for a GetUser method, it should never return the user's password in essence, so userinfo is at least one password less data than the user. In domain-driven design, as the first series of articles says, do is not a simple pojo, it has domain business logic.
DTO and do the application
from the example in the previous section, the attentive reader may find the problem: Since the userinfo returned by the GetUser method should not contain password, there should be no password this attribute definition. But if there is a CreateUser method at the same time, the incoming userinfo need to include the user's password, what to do? At the design level, the DTO that the presentation layer passes to the service layer is conceptually different from the DTOs that the service layer returns to the presentation layer, but at the implementation level, we typically rarely do this (define two userinfo, or more), because it is not necessarily wise to do so, and we can design a fully compatible DTO , when the service layer receives data, the properties that should not be set by the presentation layer (such as the total price of the order should be determined by its unit price, quantity, discount, etc.), regardless of whether the presentation layer is set up, the service layer is ignored, and when the service layer returns data, the data should not be returned (such as user password),
For do, there is one more thing to note: Why not just return to do in the service layer? This eliminates the code and conversion work for DTOs for the following reasons:
The difference in nature between the two may result in no one by one corresponding to each other, a dto may correspond to multiple do, and vice versa, and even there are many-to-many relationships.
L Do has some data that should not be known to the presentation layer
L Do has a business method, if you pass the do to the presentation layer, the Code of the presentation layer can bypass the service layer directly call it should not access the operation, for the mechanism of access control based on the AOP interception service layer, this problem is particularly prominent, and the presentation layer calls do business method also because of transaction problems, Make transactions difficult to control.
For some ORM frameworks (such as Hibernate), the "lazy load" technique is often used, and if do is exposed directly to the presentation layer, for the most part, the presentation layer is not within the scope of the transaction (opensession in view is not a worthy design in most cases), If it tries to get an associated object that is not loaded when the session is closed, a run-time exception occurs (for Hibernate, lazyinitiliaztionexception).
From the design level, the presentation layer relies on the service layer, the service layer depends on the domain layer, if do exposure, it will lead to the display layer directly dependent on the domain layer, although still a one-way dependency, but this cross-layer dependency will lead to unnecessary coupling.
For DTOs, it is also important to note that DTOs should be a "flattened two-dimensional object", for example, if the user associates several other entities (such as address, account, region, and so on), then GetUser () Return userinfo, do you want to return the DTO of the object it is associated with? If this is the case, it will inevitably lead to a large increase in data transmission volume, for distributed applications, because of the data on the network transmission, serialization and deserialization, this design is more unacceptable. If GetUser needs to return a accountid, AccountName, RegionID, Regionname, in addition to returning the basic information of the user, define these attributes to userinfo and flatten a "stereo" Object Tree "Into a" flat two-dimensional object ", the author is currently involved in a distributed system, the system regardless of 3,721, all of an object's associated objects are converted to the same structure of the Dto object tree and return, resulting in very slow performance.
Do with PO the Difference
Do and PO in most cases are one by one corresponding, PO is only contains Get/set method of Pojo, but some of the scene can still reflect the concept of the difference between the essential:
L do does not need explicit persistence in some scenarios, such as the commodity discount strategy designed with the policy model, which will derive the interface of the discount policy and the implementation classes of different discount policies, these discount policy implementation classes can be considered do, but they reside only in the static memory, do not need to persist to the persistence layer, therefore, There is no corresponding PO for this type of do.
In the same way, in some scenarios, PO also does not correspond to do, such as teacher teacher and student student there are many-to-many relationships, in a relational database, this relationship needs to be represented as an intermediate table, but also for a teacherandstudentpo Po, But this PO does not have any realistic meaning in the business field, it can not correspond with any do at all. In particular, it is stated here that not all many-to-many relationships have no business meaning, which is related to specific business scenarios, such as: the relationship between the two PO affects the specific business, and there are many types of this relationship, then this many-to-many relationship should also be represented as a do, such as: "Role" and "resources" There are many-to-many relationships, and the relationship is clearly represented as a do--"permission."
In some cases, for some persistence strategy or performance consideration, a PO may correspond to multiple do and vice versa. For example, customer customers have their contact information contacts, here is a two-to-one relationship between do, but may be due to performance considerations (extreme cases, rights as an example), in order to reduce the database connection query operation, Merge the customer and contacts two do data into a single data table. Conversely, if there is one property that is a cover cover, but this property is a picture of binary data, and some query operations do not want to load cover together, thus reducing disk IO overhead, and assuming that the ORM framework does not support attribute-level lazy loading, Then it is necessary to consider cover independent into a data table, so as to form a do to deal with a PO case.
Some of the property values of the PO do not make any sense to do, these attribute values may be to solve some persistence policy, the existence of data, for example, in order to achieve "optimistic lock", PO has a version of the properties, this version for do is not any business sense, It should not exist in do. Similarly, there may be properties in do that do not need to be persisted.
Do with PO the application
because the ORM framework is very powerful and the way it is, and Java EE has introduced the JPA specification, now the business application development, basically do not need to distinguish between do and po,po can be fully jpa,hibernate annotations/ HBM is hidden in do. Nevertheless, there are some problems that we must pay attention to:
For properties that do not need to be persisted, you need an ORM explicit declaration, such as: In JPA, you can take advantage of the @transient declaration.
For properties that exist in the PO for some persistence policy, such as version, because do, PO are merged, must be declared in do, but because this property has no business meaning to do, it is necessary to hide the property from the outside, the most common practice is to privatize the property's Get/set method , and does not even provide the Get/set method, but for hibernate, this requires special attention, because hibernate from the database read data to do, is to use the reflection mechanism to call do the empty argument constructor to construct a do instance, Then using the JavaBean specification to reflect the set method to set a value for each property, if you do not explicitly declare the set method, or set method to private, will cause hibernate to fail to initialize do, resulting in a run-time exception, It is advisable to set the property's set method to protected.
For a do corresponding to multiple po, or a PO corresponding to multiple do scenarios, as well as the attribute level of lazy loading, Hibernate provides a good support, please refer to the relevant information hibnate.
So far, I believe that everyone has a clearer understanding of VO, DTO, do, PO concepts, differences and practical application. Through the above detailed analysis, we can also summarize a principle: the analysis design level and the implementation level is completely two independent layers, even if the implementation level through a technical means can be two completely independent concept, in the analysis of design level, We still (at least in our minds) need to differentiate conceptually independent things, a principle that is important for good analytical design (the more advanced the tools, the more numb we become). The first series of blog, Big sing field driving the advantages of design, but in fact, the field-driven design in the real world is still a variety of restrictions, need for selective use, as I mentioned in the "Tianqi Wisdom" blog post, we can not always idealized to choose the so-called "best Design", in the case of necessity, We still have to dare to give up, because the most suitable design is the best design. Originally, the second blog post in the series should be to discuss the limitations and how to choose the use of the driver design, but please forgive my negligence, the next series of blog post will be the topic to fill, please pay attention.
[Turn] field-driven design articles (2)--analysis of the concept, difference and usefulness of VO, DTO, do, PO