WeedCast 4.x
-Code Documentation, 12 January 2006-
General Advice for Changing WeedCast/WheatScout Code:
Making Changes:
So, you want to make some changes to the WeedCast/WheatScout program code? Read this document first, it'll probably save you some work. If you are paid by the hour, read it twice.
Automated Tests:
First, take a moment to understand the automated tests. At the time of this writing, there are 70 tests and 2907 assertions. These tests are used to ensure the accuracy of the simulation results. These tests are facilitated by JUnit. In order to run the tests, start Eclipse, right click on the package named "test", and choose Run As>Junit Test. Then, the program will automatically run all of the tests in the java files inside that package.

More about how JUnit works

The first thing you should do before making any changes is to ensure that all of the tests pass. Even a small change to a growing degree day function can cause 20 tests to fail; the values will not be what we expected. If any tests do not pass, find out why before you continue..

After you make your changes, run the tests again. If you've done a change that you expect to change the simulation output, some tests will fail. If the numbers look okay, then you will need to update the test with the new information.

Eclipse:
You can make your changes any way you want, via any text editor. However, I'm going to assume that you'll be using Eclipse. This powerful IDE (Integrated Developer Environment), like many tools, can make your job a lot easier-- if you know how to use it.

Notes on Eclipse
Structure and Conventions:
General Structure and Organization:
The models have a highly modularized structure. For each individual calculation, there exists a method to calculate that value. For example, each weed has a method called getHeight(weather, simulationDay). This method uses the list of weather you supply and finds the height on the day specified as an argument. In addition to this information, the method may look at Main.theModel for information, such as the previous year's tillage. Since getHeight is called on a specific weed, it will also use information specific to that weed, namely the heightEquation.

We try to avoid using other static (or global) variables. This way we always know where our information comes from; we are never left wondering what the heck FoxMTSC3 came from. We can easily track backwards the values of the parameters to a method. Values in the model are not likely to change around during the evaluation of equations. These are set once by the user and stay the same for the run.

Notice that to get the height on day 50 requires the height on day 49. This is common with many of our calculations. For that reason, many calculations will take the form:
public double getCalculatedValue(LinkedList weather, int simulationDay, double otherInputValue){
	
	if (valueArray != null) {
          return valueArray[simulationDay];
      }
      //else we must calculate:
	
	valueArray = new double[weather.size()]; //create a new array of the appropriate size to hold our data

	for(int i = 0; i < weather.size(); i++){
		//for each day
		valueArray[i] += (a bunch of math);
	}
	return valueArray[simulationDay];
}

As you can see, the first call will do all of the calculations, and subsequent calls only need to look up a value we already calculated- they will not need to perform any calculations. Of course, the beauty of this is that you don't need to know how any of this works or concern yourself with the details. Whenever you call getHeight(), you will get the correct height for that day, reguardless of what calculations must be done in that method. This is an important premise of object oriented programming; we can hide complexity and trust in the fact that getHeight will give us our height. Once our automated tests have confirmed getHeight is working, we don't need to bog down our already-overburdened minds with the details of how getHeight works.

If you want to reset the values to force them to be recalculated, simply set the above valueArray to null:
	valueArray = null;

Next time getHeight is called, the values will be recalculated.
Model-View-Controller Design Pattern:
Dean Helman says:

The MVC paradigm is a way of breaking an application, or even just a piece of an application's interface, into three parts: the model, the view, and the controller. MVC was originally developed to map the traditional input, processing, output roles into the GUI realm:
Input --> Processing --> Output
Controller --> Model --> View

The user input, the modeling of the external world, and the visual feedback to the user are separated and handled by model, viewport and controller objects. The controller interprets mouse and keyboard inputs from the user and maps these user actions into commands that are sent to the model and/or viewport to effect the appropriate change. The model manages one or more data elements, responds to queries about its state, and responds to instructions to change state.


In Weedcast, the Input and Output are both taken care of in the java files found in the "gui" package. First, the user will enter their inputs to the model. They will enter a weather file and type in their site properties. When they click a button to see the output, the program reads the information and puts it into the model. Thereafter, the model does calculation on that information, without ever taking anything from the gui. After the model has done all it's math, it will return the values that the View had asked for and the view will display it however it wants.

This allows the model to be seperate from the gui. Did you know if you ripped out the entire graphical user interface, there would only be one error in the Weedcast/Wheatscout model? That one line is the line that starts the GUI. (Actually, right now there will be two errors, one error because the Weedcast window is missing and one because the wheatscout window is missing.) Other than starting the graphical interface, the code in the "src" package has nothing to do with the model.

This has the advantage of the model not needing to care what is happening to the data. The model doesn't care- and can't tell the difference between- whether the view is going to write the information to a save file, put it in a table, or put it in the graph. This way, we can be sure that if the tests find our data to be correct, it will still be correct in a table or a graph. If cases were handled differently, there would be a possibility of introducing errors that the tests would not catch.

More info about the Model view controller pattern may be found here... or on google.
Javadoc Comments:
Please be sure to comment your code. Writing clear code and giving variables and methods descriptive names will save your predecessors and your future self (you in one year, or tomorrow even) more time than will be spent writing quality code.

I have found that consistent conventions, descriptive names, and occasional comments go a long way in readability of the code. You don't need to go crazy with comments all over. A lot of code will describe itself. However, when you see something and think that you won't remember why you wrote that line, that's time for a comment.

Javadoc comments are special comments that Eclipse will automatically remember for you. This way, you can simply point your cursor over a variable name and method and it will show you that comment. In addition, you can automatically generate documentation with Javadocs. But the former feature is probably more handy, especially for a project like Weedcast.

For example, GDDs are a good thing to comment. I tend to get confused easily, especially when we have 6 different kinds of growning degree days. :( So, commenting them is really handy. In Weather.java you will find:
    /**  calculated via air temps, and is sum of all previous GDDCumulatives*/
    private Double GDDCumulative;
So when I just point my cursor over GDDCumulative, I get a nice description of what it is.

Another good example is:
    /** measured as a percent*/
    private Double soilMoisture;
    /** measured in mPA*/
    private Double soilWaterPotential;

The same can be done with methods, such as this one commonly found in the gui:
   /**
     * This will take the WeedCastWindow and fill all of the input fields with the data inside
     * the actual model (Main.theModel). So, if you programically change, for example, the
     * siteName, it will not be reflected in the actual window until you call this method.
     * In fact, the value in theModel may be overwritten when you validateInputs if you
     * don't update them first.
     */
	public void updateWindowComponentValues() {
		WeedCastWindow.txtSiteName.setText(Main.theModel.siteName);
		....
	}