Previous Article: Application Framework Design II: hierarchical and inter-layer data transfer (I)
After reading the previous article, many people commented that it may be of no practical use to give so many nouns. In fact, compared with. net, java has a lot of architectural skills. It will be much superficial if we want to talk about the architecture without talking about java. At this point, net may take many years to catch up (if you do not redouble your efforts, I am afraid it will always lag behind java ). As for VO, BO, and PO, I am afraid you are not aware of your use. In the next article, we need to analyze the popular architecture. bigtall is so daring to show the analysis results.
Bigtall has selected several popular architectures for analysis on the form conversion of DO, mainly to see how they are doing. These architectures are Petshop 4.0, Struts, tapestry, Spring MVC.
First, let's take a look at Petshop4. The project contains 22 sub-projects. We classify these sub-projects by layer-3 architecture:
Display layer: WEB CacheDependencyFactory ICacheDependency TableCacheDependency
Business Layer: Model BLL IBLLStrategy IMessaging MessagingFactory MSMQMessaging OrderProcessor
Storage layer: DALFactory IDAL DBUtility implements ledal SQLServerDAL
Permission-related independence: SQLProfileDAL ProfileDALFactory OracleProfileDAL IProfileDAL Membership Profile
Pay attention to the business layer Model, which defines all the data objects used in the project, a typical BO. Due to asp.net's componentization design, there is no clear VO concept (such as textBox1.Text ). But let's look at the AddressForm custom control code in the WEB project:
Public partial class AddressForm: System. Web. UI. UserControl {
Public AddressInfo Address {
Get {....
String firstName = WebUtility. InputText (txtFirstName. Text, 50 );
......
Return new AddressInfo (firstName, lastName, address1, address2, city, state, zip, country, phone, email );
}
Set {
If (value! = Null ){
...
If (! String. IsNullOrEmpty (value. FirstName ))
TxtFirstName. Text = value. FirstName;
...
}
}
}
}
Clearly, it is a typical code that maps VO to BO. Let's also look at the CheckOut under the same project. aspx. cs also has similar conversion code: extract data from the WEB interface control, construct OrderInfo, and finally pass in the Order class of SQLServerDAL or OracleDAL. You can see the following code:
Public void Insert (OrderInfo order ){...
OrderParms [0]. Value = order. UserId;
...
OrderParms [19]. Value = order. AuthorizationNumber. Value;
...
}
This is also a typical BO-to-PO conversion process, but we have replaced the custom PO object with a structure similar to Hashtable.
References: Microsoft. NET Pet Shop 4 architecture and technical analysis
Next let's look at Struts. All the WEB submitted data is placed in the so-called ActionForm object. For convenience, many people directly customize a structure similar to Hashtable for general ActionForm. This ActionForm is what we call VO. Then, the ActionForm is passed to the Action for processing. Generally, the Action checks the ActionForm content once, constructs the BO, and passes it to the Service layer for processing. After the Service layer completes the processing, the DAO object storage is called. Because java programs basically use hibernate or ibatis modules, the conversion from BO to PO is encapsulated.
When many people use struts or other java frameworks, they often add too many business logic code to the Action to make the Action that originally belongs to the interface layer backend into the business layer, the figure below makes it easy to make a simple forwarding call to the Service-Layer Code, similar to boolean XXService (XXBO bo) {return dao. save (bo);} is a big mistake.
Note: bigtall does not agree that the Action recognized in the references belongs to the business logic layer. In my opinion, the business logic layer determines that a service can be exposed as SOA without modifying or adding a simple wrap. Action obviously does not meet this requirement. To do this, if you have to say that Action belongs to the business logic layer, it can only be a Service encapsulation interface specifically for struts. it is not suitable to contain a large amount of business logic code.
Struts returns data to the interface layer by filling the BO in a Hashtable structure, which is used directly by the interface jsp, just like asp.
Reference: Struts, an open source implementation of MVC
The Tapestry framework is a componentized web framework that adopts similar design ideas with asp.net. When a web request is submitted to the server, tapestry fills in the content in the request to the attributes of the BasePage derived class object corresponding to the page, this is an automatic VO Filling Process (similar to the Text attribute of the TextBox object in asp.net ). Then, the BasePage derived class Object finally fills its attributes into a BO and passes them to the Service layer. The Service layer calls the DAO object to store it in the database through Hibernate or ibatis.
Return data to the interface layer using the ognl expression. The basic principle is similar to filling BO or VO In the Hashtable structure, and then selecting with the ognl expression as appropriate. It is easier to use than asp/jsp because it is componentized, so it is neat.
References: Understanding Tapestry, part 1, understanding Tapestry, part 2
Spring, as the AOP framework of No. 1, has the greatest advantage of flexibility and scalability. In the Spring MVC Framework, web requests store all user request data through the HttpServletRequest parameter (similar to a Hashtable structure) and pass it to the Controller for processing. If the Controller is derived from SimpleFormController, you can use the bind Mechanism in jsp to automatically populate the submitted data with a specified object (that is, VO ), otherwise, you must obtain it from HttpServletRequest manually. In the Controller, you can pass the data to the Service layer for processing. The processing of the Service layer is the same as that of other java frameworks.
There are many methods to return data to the interface layer. Different ViewResolver methods can be used. jsp, freemarker or velocity scripts can be used, you can also define a new interface layer description.
References: Step-by-step development of Spring Framework MVC applications
From the analysis of the above simple architectures, we can clearly see the mutual conversion process of VO/BO/PO. However, there is a characteristic that there is a clear processing and packaging for VO-to-BO conversion, but it is ignored for BO-to-VO conversion, and the exposed BO object is directly used, use ognl or other technologies for Direct values. Asp.net's WebForm is a little more complex, but it also avoids the VO problem, but the assignment is put in the class code, with less flexibility. The BO-to-PO issue tends to be handled by modules similar to ORM.
Most of the conversions between DO forms are discussed, but a very practical problem needs to be addressed, that is, the exposure of database IDs. According to our theory, ID actually belongs to PO (hereinafter referred to as POID). In fact, this POID is not required in VO and BO, and there will be many hidden risks after this POID is exposed, once the program check is not strict, it is easy to trigger a request to modify the data that should not be. But can we really discard POID? Bigtall also uses an example.
Bigtall still uses the previous LoginInfo example. However, this scenario is to query and modify specific LoginInfo. This scenario involves the following processes:
- Enter the query condition LoginInfoQuery to the service layer, and return the LoginInfoBO [] object array.
- Display the data of LoginInfoBO on the interface layer and wait for Modification
- Save the modified LoginInfoBO submitted by the interface layer to the database.
This exposes a problem. How can we make the system understand that LoginInfoBO in step 1 and Step 2 is the same object? The same problem also exists in the conversion of BO and PO. How can we convert a specific BO to a specific PO? This is why we cannot get rid of this POID. In a word, without POID, we cannot solve the problem of object ing.
Is it true that we can only map objects through POID? No! There are many ways to solve this problem, but it is better to use POID directly. For example, can we use Hashtable to store the VP ing between VP, BO, and PO? Of course we can, but I think we can use a better method, because this problem is ultimately the problem of the unique object identifier (OID.
To solve this problem, we need two conditions: one is that the object has a unique ID number OID, and the other is to save the unique ID ing relationship between VO and BO, BO and PO objects. Direct use of POID can easily meet these two conditions, but brings great program risks. Once the POID saved on the interface layer is illegally modified, it is very difficult for the program to prevent such problems, in addition, many programs simply assume that the interface layer POID is reliable. However, if the program is applied in finance, finance, and other fields, the operator is very likely to have the motivation to modify the POID of this interface layer (especially in browsers. In general, they can easily shirk their responsibilities (Program bug! Compensation is also made by software developers ). Therefore, a reliable approach is to avoid using POID as a general OID, instead of assigning an OID to each object and ensuring a simple OID ing between OID.
The OID design provided by bigtall is as follows: All DO objects inherit the IIdentitable interface, and the IIdentitable interface has a unique attribute OID. When the object is constructed, the ClassFactory or its own constructor automatically assigns values to the OID. The assignment algorithm is as follows: use simple session id conversion as the key, add the POID to a checkpoint (remember the last X of the ID number ?) The new POID is encrypted using the DES algorithm, and the encrypted result is used as the OID of BO. If necessary, the same steps can be used for BOID to VOID conversion. This algorithm ensures that the session IDs of different users for different logins are completely different, so the OID cannot be obtained through simple replication. Secondly, we need to work with the check program to prevent users from querying data that is not in the category of their own businesses, and try to check the permissions of the operation objects as much as possible.
So far, bigtall has finished explaining the morphological changes of DO. In fact, there is another important concept: DO design. Is this design important? The answer is very important! See bigtall's "Application Framework Design 3: data transfer object type and design ".
---
2009-8-12 correct DO's mistake in DTO.