Last Updated 3/31/01- Go Back
Iteration 4, March 15 Meeting
Iteration 5, March 2 Meeting
Iteration 4, March 15 Meeting
At this meeting we did Iteration 4, which added the "Reuse a Container Branch" feature. Download Iteration 4. First we designed how to do this. Here's the artifact, which still fits on one page:
Our process includes the Goal and Implementation Plan for Iterations 4 and 5. This allows us to "Plan your work, then work your plan". As we did Iteration 4 we checked off each step as we did it with "(done)".
The "Extract DKStore from Container" step keeps the Container class from growing too big, and opens the door for reusing DKStore. DKStore is a "delegate" of Container, allowing it to delegate a responsiblity. In Iteration 5 Container will probably get another delegate to do relatiionships.
Notice the redesigned container DK. It now includes an example of a container URL for locating the container to reuse. Since we are reusing DK files instead of classes we need to create our own mechanism. The URL approach, which uses Class.getResourceAsStream(), is a fine and flexible solution. Class "markers" are a very powerful mechanism indeed. We discussed them some more at this meeting.
This framework has become a good example of how even a very small number of classes can offer substantial productivity improvement. Notice we have only four classes so far. We also have the Datatron package, ListOne and the ClassResourceReader, but we didn't have to write these - they are third party reusables. What does our four class framework do so far?
1. Creates a tree of nested containers and leafs from Dk files.
2. Supplies leafs with their DK if they are DK driven.
3. Ability to reuse a container branch.When you consider the tree can be infinitely large, and so can reuse container branches, that's not so bad for four classes. What might a framework like this be used for? It allows a company to design a collection of highly reusable components and assemble them into systems with no code. The systems can be large or small. For example many EJB components are subsystem entry points. Such subsystems could use this framework, allowing them to be more organized, easier to maintain, easier to reconfigure and easier to reuse small components. Note that system DK itself can be defined at runtime, allowing real time assembly of the exact system needed to perform a job.
Iteration 5, March 29 Meeting
At this meeting we did Iteration 5, which added the "Set leaf relationships from DK" feature. Download Iteration 5 . Here's the artifact:
This iteration completed the framework series. This rather tiny framework now has the minimum features necessary to create an object graph from DK. Since the component relationships are determined by DK and not the components, the component are far more reusable. This sort of thing is the the main reason we did this framework series - to show how, with very little code, a simple but powerful framework can be created. Those who followed this series should come away more knowledgable of frameworks, and with the confidence to design their own when the opportunity arises.
Note the Implementation Plan for Iteration 5. This allowed us to Plan our Work, and then Work our Plan. While this may not be needed on small projects, doing it will allow your personal process to seamlessly scale up to large projects, where such planning is crucial.
Most of the implementation effort in this iteration was in the Container class. This method has the key code:
/** * Returns the named reference. Throws an IllegalArgumentException * if not found. This method uses the References section of * the container DK. Note that only currently the only location * supported is a leaf in the same container. */ public Object getReference(String referenceName, String leafName) { // Get node DK for leafName Datatron nodeDK = (Datatron)nodesDK.get(leafName); if (nodeDK == null) throw new IllegalStateException ("No DK for node named " + leafName); // Get reference DK for referenceName Datatron refDK = getNodeReferenceDK(referenceName, nodeDK); if (refDK == null) throw new IllegalStateException ("No reference DK for reference " + referenceName + " in node named " + leafName); // Get Location from reference DK String location = refDK.getString("Location"); // Navigate to Location to get reference // *** Only in same container supported for now // *** The Location must be leaf name, same container Object reference = nodes.get(location); if (reference == null) throw new IllegalStateException ("No reference for location" + location + " in node named " + leafName + ", reference name " + referenceName); // Assert reference Type is correct // *** Later // Return reference return reference; } |
This method illustrates several important techniques. Basically datatrons are used to transport and read DK. The DK determines the policy of the component for this reuse case.
<Nodes>
....<Node>
........<Name>LeafA</Name>
........<Type>jsl.fw1.qc.Leaf1</Type>
........<References>
............<Reference>
................<Name>LedgerEntry</Name>
................<Type>jsl.inv.ap.Ledger</Type>
................<Location>ContainerB/LeafB</Location>
................</Reference>
............</References>
........</Node>
....</Nodes>To the right is our design sample of the DK being processed in this method.
In "Get nodeDK for leafName", nodesDK already contains the DK for each node, so this method can easily retreive the DK for the node named leafName.
In "Get reference DK for referenceName", we wrote a sub method to do the real work, getNodeReferenceDK(). See the Container class for this code. It returns the DK describing a Reference, which is the Name, Type and Location.
Note the use of assertions which throw exceptions if they fail. This is a good practice. Note the very readable exception messages. These help pinpoint bugs if they occur.
In "Get Location from reference DK", we make use of the well designed Datatron class, retreiving the Location String in one line of code. Looking at the sample DK, this would be "ContainerB/LeafB".
In "Navigate to Location to get reference", the only Location we support is a leaf name in the same container. It's common to support only simple behavior in first versions such as this method.
In "Assert reference Type is correct", we do nothing. This can be done later. It's not required to run, but rather is a way for the system to check its own consistency.
Final Comments
Well, those are the highlights. To get the most out of this framework excercse, we recommend:
1. Run Iteration 5. Examine the output and check the code producing it.
2. Examine the file structure for system1. Understand the DK files.
3. Make changes to the DK files, run system1, and watch the output change.
4. Add some DK files and edit container DK. Run it and check the effects. Do this until you completely understand what the DK files are doing, where they must be, what they must contain.
5. Consider why the DK files were designed the way they are. Could you improve on this?
6. Complete Container.getReference() for the "Navigate to Location to get Reference". Support relationships to leafs anywhere in the container tree. Also complete the "Assert reference Type is correct" section.
7. Examine the artifact. Does it make complete sense? Could it be better?
8. Given the artifact, implement it from scratch. Peek at the existing code if needed. Do this until you could do it without peeking.
9. Given the requirements, create the design.
10. Now that you're a raw, over confident DK framework expert :-), think of a domain that could use some of the techniques presented here. Do a Mini Process on it, all the way to a small running version.
All this will maximize your learning experience. Good luck. :-)