34.12. Materialization with the Template Method Pattern

If we were to program two or three mapper classes, some commonality in the code would become apparent. The basic repeating algorithm structure for materializing an object is:

						if (object in cache)
						return it
						else
						create the object from its representation in storage
						save object in cache
						return it
					

The point of variation is how the object is created from storage.

We will create the get method to be the template method in an abstract superclass AbstractPersistenceMapper that defines the template, and use a hook method in subclasses for the varying part. Figure 34.7 shows the essential design.

Figure 34.7. Template Method for mapper objects.


As shown in this example, it is common for the template method to be public, and the hook method to be protected. AbstractPersistenceMapper and IMapper are part of the PFW. Now, an application programmer can plug into this framework by adding a subclass, and overriding or implementing the getObjectFromStorage hook method. Figure 34.8 shows an example.

Figure 34.8. Overriding the hook method.[4]


[4] In Java as an example, the dbRec that is returned from executing a SQL query will be a JDBC ResultSet.

Assume in the hook method implementation of Figure 34.8 that the beginning part of the algorithm—doing a SQL SELECT—is the same for all objects, only the database table name varies.[5] If that assumption held, then once again, the Template Method pattern could be applied to factor out the varying and unvarying parts of the algorithm. In Figure 34.9, the tricky part is that AbstractRDBMapper--getObjectFromStorage is a hook method with respect to AbstractPersistenceMapper--get, but a template method with respect to the new hook method getObjectFromRecord.

[5] In many cases, the situation is not so simple. An object may be derived from data from two or more tables or from multiple databases, in which case, the first version of the Template Method design offers more flexibility.

Figure 34.9. Tightening up the code with the Template Method again.


UML notation— Observe how constructors can be declared in the UML. The stereotype is optional, and if the naming convention of constructor name equal to class name is used, probably unnecessary.

Now, IMapper, AbstractPersistenceMapper, and AbstractRDBMapper are part of the framework. The application programmer needs only to add his or her subclass, such as ProductSpecificationRDBMapper, and ensure it is created with the table name (to pass via constructor chaining up to the AbstractRDBMapper).

The Database Mapper class hierarchy is an essential part of the framework; new subclasses may be added by the application programmer to customize it for new kinds of persistent storage mechanisms or for new particular tables or files within an existing storage mechanism. Figure 34.10 shows some of the package and class structure. Notice that the NextGen-specific classes do not belong in the general technical services Persistence package. I think this diagram, combined with Figure 34.9, illustrates the value of a visual language like the UML to describe parts of software; this succinctly conveys much information.

Figure 34.10. The persistence framework.


Notice the class ProductSpecificationInMemoryTestDataMapper. Such classes can be used to serve up hard-coded objects for testing, without accessing any external persistent store.

The UP and the Software Architecture Document

In terms of the UP and documentation, recall that the SAD is a learning aid for future developers, which contains architectural views of key noteworthy ideas. Including diagrams such as Figure 34.9 and Figure 34.10 in the SAD for the NextGen project is very much in the spirit of the kind of information an SAD should contain.

Synchronized or Guarded Methods in the UML

The AbstractPersistenceMapper--get method contains critical section code that is not thread safe—the same object could be being materialized concurrently on different threads. As a technical service subsystem, the persistence service needs to be designed with thread safety in mind. Indeed, the entire subsystem may be distributed to a separate process on another computer, with the PersistenceFacade transformed into a remote server object, and with many threads simultaneously running in the subsystem, serving multiple clients.

The method should therefore have thread concurrency control—if using Java, add the synchronized keyword. Figure 34.11 illustrates a synchronized method in a class diagram.

Figure 34.11. Guarded methods in the UML.


..................Content has been hidden....................

You can't read the all page of ebook, please click here login for view all page.
Reset
3.147.49.106