Copyright © 2002
The Feynman Project
Before reading this section make sure that you have a good understanding of the Java programming language, the Unified Modelling Language (UML) and what are known as Design Patterns. If you are just getting started with Java or if you are not familiar with UML and Design Patterns the suggested reading listed below will help bring you up to speed:
That is a lot of reading but in reality if you make it through the first 7 or 8 chapters of Learning Java as well as the chapters on UML and Factory patterns in Design Patterns Explained, you will be more than ready for this overview. In fact, developing the sample application will help you understand the concepts covered in those chapters.
To really understand the Framework we first try to break down the problem that it is intended
to solve and assist developers with.
Problem Statement - To solve a physical problem that can be numerically simulated.
Lets examine how physicists typically breakdown this problem. We first start with a physical system that is being studied. In the sample application the physical system consists of a ball under the influence of gravity. Every problem has some type of physical object that is in the system of study and for our example it is a ball. To provide a point of reference in the physical system, a coordinate system is chosen so that physical objects can be tracked in some manner. The diagram below shows how the Framework relates these entities in terms of abstract classes.
As you can see, the PhysicalSystem and PhysicalObject are the top level classes in our design. The relationship between a PhysicalSystem and a PhysicalObject is a has a aggregation relationship as indicated by the diamond. In laymans terms this means that PhysicalSystem is made up of or composed of PhysicalObjects.
The selected coordinate system is realized in the sub-classes of the two parent classes. The idea being that other systems and objects specified by other coordinate systems can be created as sub-classes as well. Note that an aspect of the CartesianSystem subclass is to ensure that all objects that are added to this system are of the type CartesianObject. This makes it easy for developers of applications to build a consistent system without having to check this manually in their application code.
How does the Framework use these two classes and expand on them as the basis? Notice in the UML diagram that these are abstract classes meaning they cannot be instantiated. They were designed that way to make use of the Factory and Abstract Factory patterns. For now just take the idea of a factory as an standard way of creating objects that are similar but not necessarily related. An abstract factory creates similar objects in a standard way where the objects are related. Since there can be several types of PhysicalSystems depending on the selected coordinate system (or lack of one in some instances), a factory is designed to assist in the creation of those objects. Likewise, for PhysicalObjects, an abstract factory is is used to create them. A more detailed UML class diagram is shown below:
These are some of the classes that make up the feynman.framework.system package. The top level to the diagram is the PhysicalSystemFactory. This class is a concrete class and is responsible for creating the user specified PhysicalSystem. It does so by creating an instance of the user specified PhysicalSystem and adds to it the specified number of PhysicalObjects using the appropriate PhysicalObjectFactory.
The next part to understand is the relationship between the remaining classes in the system package and their relationship to the Controller in the feynman.framework.controller package. The UML diagram below shows them:
The classes on the right side of the arrows are Interfaces. An interface specifies a public contract that the implementing class of it must agree to. For example, the FinalReport interface specifies there must be a public class named report that takes a Simulation and PhysicalSystem instances as arguments.
As was pointed out in the Controller section, the Controller class has two responsibilities. First it creates instances of the user specified classes that implement the interfaces shown in the figure above. It also is responsible for invoking methods to perform the actions of each class that implements the interface at the appropriate time. Following the report example, the Controller will create an instance of FinalReport class and the report method will be invoked after the simulation is complete.The four interfaces shown here are the ones that each developer intending to use the Framework will have to provide implementations for. The following table provides more information about each interface. It is suggested that you read the JavaDoc for each interface to become more familiar with them.
In the next section you will see how the sample application provides implementations of these interfaces but for now it is useful to understand what each is meant to provide. The names of each interface are pretty self explanatory. The PhysicalConfiguration class implementation is meant to setup the initial conditions of the simulation. In the sample application it sets the balls initial height and velocity. The Controller uses the PhysicalAlgorithm class implementation to numerically integrate the equations governing the simulation. In the sample application the Euler algorithm is implemented for the ball's equations of motion. The PhysicalMeasurement class implementation dictates what physical quantities will be periodically measured. The FinalReport is provided so that summary statistics and final calculations can be reported to the user in a simple text format.
If you examine the arguments of some of the methods listed in the table above you will see they take a Simulation object. To this point we have mentioned this class and also discussed the simulation in terms of using a computer program to manipulate numerical equations to simulate a real physical system. It is part of the feynman.framework.simulation package and is a JavaBean. This is yet another new term, but think of a bean as a class with properties that can be set using a setter method and retrieved using a get method. The experienced Java developer you will note the Simulation class is a Singleton since there is only one simulation being performed at a time. As a Framework developer who is just getting started you will be happy to note that of the 19 properties to date, you will only really need to concern yourself with a few and they will be covered in the sample application section.
There is one other class in the feynman.framework.simulation package. The Marshaller class is responsible for processes known as marshalling and unmarshalling the Simulation object. Using Java's dynamic data binding capabilities, when the the Controller was mentioned to create a Simulation from the Simulation.properties file, it does this by invoking the marshall() method of the Marshaller class. This method retrieves an instance of the Simulation class using the getInstance() method. Based on the values in the properties file, it then sets the values of the properties you specified.
The last package in the framework is the feynman.framework.datastore package. The purpose of the classes in this package is to make it transparent to the Contoller class how it saves the data taken during a PhysicalMeasurement.
The DataStore interface specifies that an implementation must provide methods to open(), save() and close() a data store. The only class implementation to date is the FileDataStore which uses the toString() method of the PhysicalMeasurement class. It is planned to add relational database capabilities using the DbmsDataStore that would make use of the toSql() method. Unless you are curious about the source code for the implementation classes, it suffices that the knowledgeable Framework user understand how the FileDataStore and DbmsDataStore use the appropriate method from the PhysicalMeasurement class.