For vs. For-Each Construct

Posted on Tuesday, September 30, 2008
1 commentAdd comments

In his blog Automated QA vs. Manual QA: CodeRuler Revisted, Arthur Shum states that I 'identified a false error' and that use of the for construct was necessary to provide access to the indices for the implementation to function as desired. I stand by my observation that use of the for statements I cited in Peer Review: Adhering to Java Programming Standards can be replaced with for-each constructs and still maintain the desired results:

Case 1 – Iterating over myKnights (Line 113):

for construct:
   1:  for (int i = 0; i < numOfKnights; i++) {
2: if (i < numOfKnights * .2) {
3: team1.add(myKnights[i]);
4: }
5: else {
6: team2.add(myKnights[i]);
7: }
8: }

for-each construct:
   1:  for (IKnight k : myKnights) {
2: // Assign one-fifth of knights to team 1
3: if (team1.size() < numOfKnights * .2) {
4: team1.add(k);
5: }
6: // Assign remaining knights to team 2
7: else {
8: team2.add(k);
9: }
10: }

Case 2 – Iterating over myPeasants (Line 189):
This example still requires knowledge of the peasantIndex variable, but it has been implemented as a counter-index variable for use in only 2 lines of code outside of the declaration/incrementation statements. I have commented out the code I replace in order to use the for-each construct:

   1:  int peasantIndex = 0;
2: // for (int peasantIndex = 0; peasantIndex < myPeasants.length; peasantIndex++) {
3: for (IPeasant p : myPeasants) {
4: directions.clear();
5: int curX = p.getX(); // myPeasants[peasantIndex].getX();
6: int curY = p.getY(); // myPeasants[peasantIndex].getY();
7:  
8: for (int i = 1; i <= 8; i++) {
9: possibleNextPosition = World.getPositionAfterMove(curX, curY, i);
10: if ((possibleNextPosition != null)
11: && (World.getLandOwner(possibleNextPosition.x, possibleNextPosition.y) != this)
12: && (World.getObjectAt(possibleNextPosition.x, possibleNextPosition.y) == null)) {
13: directions.add(i);
14: }
15: }
16: if (directions.size() > 0) {
17: move(p, directions.get(rand.nextInt(directions.size())));
18: // move(myPeasants[peasantIndex], directions.get(rand.nextInt(directions.size())));
19: }
20: else if (enemyPeasants.length > 0) {
21: // Splits up the ruler's peasants to move toward different enemy peasants in search of land.
22: // Uses modulo so that it does not matter if there are less ore more enemy peasants.
23: int x = enemyPeasants[peasantIndex % enemyPeasants.length].getX();
24: int y = enemyPeasants[peasantIndex % enemyPeasants.length].getY();
25: move(p, p.getDirectionTo(x, y));
26: // move(myPeasants[peasantIndex], myPeasants[peasantIndex].getDirectionTo(x, y));
27: }
28: else if (enemyCastles.length > 0) {
29: int r = rand.nextInt(enemyCastles.length);
30: int x = enemyCastles[r].getX();
31: int y = enemyCastles[r].getY();
32: move(p, p.getDirectionTo(x, y));
33: // move(myPeasants[peasantIndex], myPeasants[peasantIndex].getDirectionTo(x, y));
34: }
35: else {
36: move(p, rand.nextInt(8) + 1);
37: // move(myPeasants[peasantIndex], rand.nextInt(8) + 1);
38: }
39: peasantIndex++;
40: }

When I first start thinking of this topic, I perceived the relationship between manual and automated quality assurance methodologies as an either/or relationship. I believed the relationship to be that of one being a better suited methodology over the other. Of course, that tendency would be to favor automation tools over a manual process. However, this is a fundamentally flawed belief.
“Manual and automated quality assurance methodologies are integral components
with each complementing the other in the creation of high quality, stable solutions.”


The longer I thought on the topic, the more I came to the realization that each has its strengths complementing the weaknesses the other methodology exhibits. This becomes evident in analyzing the overlaps and disparity between peer reviews and the results of running quality assurance tools (QATs) against the CodeRuler implementation from my blog entry “Lessons Learned From CodeRuler”. The peer reviews associated with this analysis are provided by
• John Ly, CodeRuler Review• Creighton Okada, CodeRuler Review
Analysis
John and Creighton succeeded in discovering six types of uniquely occurring errors, while the QATs located nine uniquely occurring error types. Of these errors only three errors were identified by both peers and the QATs—lines exceeding 100 characters, usage of a wildcard import statement, and use of tabulation versus spaces. These errors are attributed to violations against programming styling specifications.

The remaining peer errors relate to poor choice of variable naming and the capacity to clarify documentation of the implementation. The QATs identified four additional deviations from the prescribed programming styling specifications (Checkstyle) and two from good programming practices (PMD). The stylistic issues ranged from missing spacing around braces and operands to missing documentation blocks. The latter problems were due to loose coupling (usage of ListArray) [4 occurrences] and confusing ternary (using not equal as the leading condition statement) [9 occurrences]. There were no issues in the CodeRuler implementation recognized through “bug pattern” analysis (FindBugs).

Conclusion
QATs have the advantage over peers in this analysis in respect to identifying the types of coding errors they specialize in, as well as, identifying all occurrences of these errors. QATs are developed to expressly and comprehensively locate all deviations from standard programming practices (stylistic and pattern analysis). QATs have the capability to do this quickly, repetitively, and reliably. Whereas, leaving reviews of code to humans is likely to be slow and very unreliable, especially in subsequent reviews of code already reviewed which may cause the human reader to read over errors.

However, manual reviews by humans can accomplish goals that QATs are not capable of resolving. These goals include writing concise, clear and appropriate levels of documentation. Also, a manual process can ensure that the conceptual model is reflected appropriately and accurately within the implementation with proper naming of variables and member fields, that the implementation and the documentation are in sync with one another, and that the code strives to be readable and self documenting. All tasks that QATs are not capable of performing. Thus, defining the complementary relationship manual and automated quality assurance methodologies have.

Stable Builds: Using Ant and QA Tools

Posted on Friday, September 19, 2008
0 commentsAdd comments

“Even the ant has his bite.” — Turkish Proverb

I doubt the Turks had Apache’s Ant in mind when they popularized this proverb. But, I definitely felt Ant’s bite when working through the tasks outlined in a recent software engineering assignment. The assignment consisted of three tasks, each task comprised of several steps—you know, in that way college assignments seem to be constructed.
1, 2... What Do I Do?
Okay, okay, so maybe it wasn’t as bad as being bit by a bullet ant, but getting through the first task definitely stung a little. The first step of the initial assignment task was to install Ant along with several Quality Assurance (QA) tools—JUnit, PMD, FindBugs, and Checkstyle. So, first things first, install Ant... I decompressed the zip file, moved the files to the appropriate directory location, and then tried to build Ant. But, several failed attempts to build Ant led me to peruse the manual (%ANT_HOME%\docs\manual\install.html). I followed the instructions under Setup and Windows and OS/2. But still Ant failed to build successfully. I needed a better clue. I needed to know what to do.
3, 4... Chores Galore
That initial sting could have been avoided just a bit, if I had just read the Ant build error messages closer. My Ant build had issues, it first needed JUnit. Okay, not a problem. Just install the QA tools first. Checkstyle, FindBugs, and PMD all installed easy enough. (Note: Some decompressed folders added an extra root folder that I had to remove in order for the QA tool to build correctly.) After that, a quick trip to the Windows Control Panel > System > Advanced System Settings > Environment Variables dialog to create or edit the system variables:

• ANT_HOME = C:\dev-tools\ant-1.7.1• CHECKSTYLE_HOME = C:\dev-tools\checkstyle-5.0-beta01• CLASSPATH = .;• FINDBUGS_HOME = C:\dev-tools\findbugs-1.3.5• JUNIT_HOME = C:\dev-tools\junit4.5• Path = Added %ANT_HOME%\bin;• PMD_HOME = C:\dev-tools\pmd-bin-4.2.3
JUnit took a little work to get a successful build. After looking under Installation in the JUnit manual (%JUNIT_HOME%\README.html), I entered the commands there and it finally worked. Now, I was ready to attempt another Ant build. It was a successful build. I downloaded the necessary assignment files, and completed the remaining chores in the first task.

Revision: Reference to JUnit jar executable file removed from CLASSPATH environment variable. It was indicated this was a suboptimal strategy to maintain the prime directives of software engineering. See my blog JFreeChart: Open Source Charting Solutions for more on prime directives.

5, 6... Stack Gets Fixed
The second task was basically a repeat of the first (minus the lengthy installation step). It required making a copy of the downloaded assignment files, a simple Stack implementation riddled with a handful of errors. These errors were purposely left in the source files, as the objective of the assignment was to become familiar with using QA tools to improve the stability of Java projects.

The third and final task picked up here by requiring the errors identified from by the various QA tools be corrected. Once all the errors had been appropriately addressed, the corrected files (compressed) were to be posted to the web for review. My compressed, corrected Stack implementation is available here:

• Stack-Reeves-6.0.919.zip

7, 8... E-LIM-I-NATE!
The biggest issue I had with using the QA tools was that I thought I could first run all of them, then go back and look at the errors identified by each. Unfortunately, running some QA tools causes the \build directory to be cleaned and rebuilt when being run. This causes the information from a QA tool run prior to these to be erased. It took me a few times attempting this method, before realizing what was occurring. Once I figured this out, it was just a matter of correcting the errors identified by each QA tool before running the next QA tool.

Most of the errors were simple to eliminate—move a { to the line above, add final to the declaration of the member fields, and other errors of this ilk. The error that caused me the most frustration was determining what to do with an empty catch block in the testIllegalPop() method in the TestStack class. My first attempts were to throw an EmptyStackException() error, but this caused the build’s JUnit task to fail. Then, I thought I’d try using fail() in the catch block, but that too caused the build’s JUnit task to fail. Finally, I realized the problem. The catch block was actually the valid case of the method. The method is testIllegalPop(), therefore, the try block actually causes the catch block to be invoked. I decided an appropriate way to handle this, since creating a log file was too much overhead for this simple assignment, was to use a System.out.println() command to report the successful catch of the illegal pop attempt to the shell. Eliminating this last error allowed all QA tools to successfully pass the Stack-Reeves implementation. The verify task completed successfully, and I ran the dist task to create the compressed Stack-Reeves files.

Revision: “Bogus” was used to describe my use of the System.out.println() command to resolve the error caused by the empty catch block. Admittedly, this was a bogus solution and used to resolve the issue with minimal effort. Therefore, I have gone back and resolved the issue using a more elegant—and production appropriate—technique as described in the article An early look at JUnit 4.

9, 10... Fini. Fin.
Overall, I am impressed with Ant. While it may have been challenging to get set up initially, its power become evident quickly on during the build processes. It is easy to see what the lowly ant and Apache’s Ant have in common: each is a tiny implementation (one biological, one digital) that does much more than seems it should be capable of doing. Nature’s ant can lift 100 times its body weight, whereas Apache’s Ant can verify Java projects containing 100 times (and more) lines than in the build.xml files. In addition, being my first experience with these QA tools, I am truly amazed. It is great to have a set of standards—very close to ones I have been using personally for several years, which can be verified against so simply and comprehensively to create stable project builds.

Peer Review: Adhering to Java Programming Standards

Posted on Thursday, September 11, 2008
0 commentsAdd comments

In Lessons Learned From CodeRuler, I explored how that project influenced my understanding of the Java language, the Eclipse IDE, and especially, peer programming. In this article I continue that exploration of peer programming by examining and evaluating the CodeRuler implementation from a group of peers in my ICS 413 course this semester. The main aspect of the evaluation is the adherence to Java programming standards defined by these sources:

• The Elements of Java Style by Vermeulen, Ambler, Bumgardner, Metz, Misfeldt, Shur, & Thompson• ICS 413 Supplemental Standards from Philip Johnson
The Elements of Java Style (EJS) had been informally introduced prior to the CodeRuler assignment to the class, but had not yet been mandated as the formal coding style to which course work should adhere. The latter standards, referred to as ICS-SE-Java or ICS-SE-Eclipse, were introduced to the class after completion of the CodeRuler project. Doing the CodeRuler assignments in this manner provides each developer within the class the opportunity to discover his/her baseline adherence to the standards expected through code reviews of our peers’ course work. By discovering deviations from the standards by our peers, we learn to look for deviations in our own programming methodology. Additionally, this assignment begins our exposure to the expectations that will be placed on us as programmers entering into the workforce, as well as laying down a foundation of programming best practices and tools we will need for our eventually rise into management and executive positions.

Peers Being Reviewed
For the purpose of this review, I will be examining the CodeRuler implementation provided by

• Arthur Shum (Check out his CodeRuler blog entry.)• Aric West (Check out his CodeRuler blog entry.)
Their implementation may be downloaded directly from either’s blog or from here:

• aricwest-atshum.zip
The Good
To say that this implementation provides an effective solution to the CodeRuler challenge would be an understatement. Even its designers describe it as an “aggressive” solution. Ruthless is probably a better word. This implementation is quite successful, and after watching it successfully conquer ruler after ruler in just a few moments of game play, even in 3 to 6 ruler competitions, I had difficulty finding a better suited word than “ruthless” to describe West-Shum’s implementation. Their ruler does quite a good job of dispatching opposing rulers and their forces in a very short period. The salt-in-the-wound for opposing rulers is West-Shum’s boxing of enemy peasants by using their peasants such that the opposing peasants are unable to move, and this on top of having already decimated all opposing offensive and defensive units.

The supporting JavaDocs are in order with short, concise descriptions of how to use their implementation. The documentation is easy to read, well-organized, and defines the class and implementation features appropriately.

For the most part, the class definition (MyRuler.java) is organized appropriately being arranged such that readability is reinforced.

The Bad
The following table displays the violations of the EJS, ICS-SE-Java, and ICS-SE-Eclipse standards occurring within the West-Shum implementation of CodeRuler.

Source Code File:  MyRuler.java

LinesViolationComments
-ICS-SE-Java-1Code not contained in package hierarchy edu.hawaii.
6ICS-SE-Java-2Wildcard * used in import statement (com.ibm.ruler.*).
113, 189ICS-SE-Java-9Use for-each control structure to iterate over myKnights and myPeasants arrays.
9, 86, 87, *ICS-SE-Eclipse-2 /
EJS-6
Keep lines under 100 characters by breaking up into shorter lines.
44, 45, 49, *EJS-9Use descriptive names for variables to convey implementation concepts.
114, 154, 217, *EJS-9Create class or method level variables in place of “magic” numbers.
102, 103, 104, *EJS-29Use fully qualified field variable names by prefixing with this keyword.
99, 185EJS-69Design smaller methods by refactoring similar code blocks out and having them do only one task.
* Denotes this violation occurs in additional lines of code not indicated.
And What I’d Suggest
By in large these violations of the standards are minor issues that can easily be addressed by these adept programmers. Their ability to program well is evident in the success of their solution, and being as such, addressing these minor infractions will require little more than an awareness of them. However, I have two observations regarding the implementation that I personally would change: 1) keeping the methods smaller and focused to a single task, and 2) more appropriate use of member fields. Regarding the first observation, the orderSubjects method performs 6 tasks within its body: gather information, create knight teams, prioritize enemies, attack enemies, order peasants, and castle production. I would suggest breaking most of these code blocks into separate methods, such that orderSubjects reads similar to
   1  public void orderSubjects(int lastMoveTime) {
2 //Gather information
3 this.myPeasants = getPeasants();
4 this.myKnights = getKnights();
5 this.myCastles = getCastles();
6 this.enemyCastles = World.getOtherCastles();
7 this.enemyKnights = World.getOtherKnights();
8 this.enemyPeasants = World.getOtherPeasants();
9
10 createTeams();
11 prioritizeEnemies();
12 attackEnemies();
13 orderPeasants();
14 controlProduction();
15 }
Of course, this is just my personal style, but I prefer this style due to its readability and the ability to focus on the specific components in the larger method.

The second observation is that some variables seem to be unnecessarily long lived. For example, several field members are created (i.e., myCastles, myKnights, myPeasants), then initialized on each call of the orderSubjects method. These are then passed as method parameters throughout the rest of the implementation, instead of using direct calls to them. There is one instance where the myKnights member field is referenced directly, but it could just as easily been passed as a parameter by the calling method. I don’t see any benefit to making these member fields, since they are not used in that capacity within the implementation. Personally, I would just make these method level variables and pass as method parameters as needed from the orderSubjects method.

Lessons Learned From CodeRuler

Posted on Monday, September 08, 2008
0 commentsAdd comments

Peer Programmers


What is CodeRuler?
CodeRuler is a medieval simulation game that allows game programmers, students of the Java programming language, as well as, any person interested in strategy/simulation games to create his own personification of a ruler in a predefined world. The CodeRuler world provides a tournament-style competition, where a player may pit his ruler against zero to five opposing rulers at once, including rulers using the same strategy as his.

The objective is to achieve the most points by the end of 500 turns. Each ruler has .5 seconds to complete his turn each round, and if the time limit is exceeded in any round, all future turns are forfeited. Points are earned by peasants through the accumulation resources for the ruler, which are awarded at the end of the game. For every 10 units of resources, 1 point is awarded; in addition, 1 point is awarded for each remaining peasant. Knights earn the ruler points by a) taking enemy peasants (4 points), b) eliminating enemy knights (6 points), or c) conquering enemy castles (15 points). Each remaining knight at game end earns 2 points. Finally, for every castle controlled by the ruler, another 25 points is added to the final score. If a ruler losses all subjects and castles, he is eliminated from game play, however, the game continues until all turns have been completed. This allows the remaining ruler(s) to amass as many points possible in the remaining turns.

Strategy Implemented
Our strategy was three-fold: 1) use the peasants to acquire as many resources as possible, 2) use knights to control the economy of opposing forces, and 3) control our economy based on the enemy units in play.

We implemented a box pattern path for our peasants to move around the world. This path would direct peasants south, east, north, and west and continuing throughout game play or until no peasants existed. This pattern had a great deal of success by getting the peasants into the other ruler’s kingdom. Once there, due to the box pattern, our peasants would take control of enemy resources. The fewer resources a ruler has, his unit production time increases (the number of turns required to create a new unit in the game). This was the key to our first objective, and lent itself to achieving our second objective as well. We kept the direction acquisition of resources to random moves versus a directed pattern. Finally, we implemented an evasion tactic for the peasants when enemy forces neared their position.

To achieve the knights’ objectives, we chose to have knights attack castles first to eliminate the opposing ruler’s production facility. Once the opposing ruler’s castle was secured, we targeted enemy peasants. This strategy prevented new enemy units from being placed into play, and decreased enemy resources such that if enemy units already in play were able to take or reclaim a castle, their production time would be so high, new units would have a difficult time getting into play before our knights retook the castle. Finally, the knights would target enemy knights in an effort to prevent them from accumulating points from taking our castle, peasants, and knights.

Lastly, the castle was used to control our economy in different ways throughout game play. If our economy was healthy and no enemy units existed, we produced peasants. If an enemy castle existed or enemy knights existed, we would attempt to keep at least 10 knights in play while we had more than 15 peasants in play as well. If our peasants dropped below 15, then we would create more in an attempt to increase resource accumulation.

Lessons Learned
• Eclipse IDE
Eclipse continues to be challenging to use. Its compiler seems to respond slowly to unflagging errors that have been corrected. Occasionally, I needed to save the file to remove the flagged errors that had already been corrected. Other IDEs that I have used bold the opening and closing brackets for a code block, which I prefer over Eclipse’s placing a small light grey border around the matching bracket set. Other features that would be nice to have is a comment/uncomment code and increase/decrease indentation of code commands. Other IDEs typically have these, yet I have not found them in Eclipse.

• CodeRuler Implementation
CodeRuler was a fun experience. It is one of the few games I have had the opportunity to work on. I am typically better at playing a strategy game (e.g., Risk), than trying to implement or create one. Coming from a business intelligence background, simulation game design is challenging to me as most are based on strategy, while my strengths surround analyzing and understanding the relationship of data. Choosing an interesting and viable strategy was the most difficult and interesting aspect of the process.

One of the most rewarding experiences during developing our implementation was creating the evasion tactic for peasants. Once implemented, it was humorous to watch enemy knights chase after some peasants for a fair distance.

• Java Language
I have not had the opportunity to use JavaDocs to great extent. While my partner created the JavaDocs, and I reviewed them, going over the inclusion of JavaDocs attributes in the code was a valuable experience. I never realized how simple they were to add to a project, and the resulting documentation is quite impressive.

Another aspect I learned about Java is roughly how much code can execute in less than .5 seconds.

• Peer Programming
I have not typically enjoyed peer programming experiences in the past with fellow students. For varying reasons, finding time to meet is the biggest factor, the second being the balancing of responsibility and contribution.

Working with Robin has really changed my perspective of the peer programming process. He was very easy to work with and our collaboration seemed very natural. We used Skype to do the majority of our work, as we do not live near one another and this seemed to work well with our schedules. We did meet on separate occasions, spending time at UH’s Hamilton Library to hack code. But, I think using Skype actually worked best for us. We were able to work in areas we were comfortable (our homes) and share files throughout the process. Additionally, Skype keeps a history of the conversation, so we could easily pass code changes to one another by file or pasting directly into the chat window. This sped up the development process considerably. We both shared responsibility of the project and each jumping into the problem solving and communicating effectively with each other.

Run Results Against...Migrate Ruler
RunRaqueno-ReevesMigrateEnemy Status
16946Dead
267614Dead
36522Dead

Gang Up Ruler
RunRaqueno-ReevesGang UpEnemy Status
1516232Dead
2586133Dead
3525233Dead

Split Up Ruler
RunRaqueno-ReevesSplit UpEnemy Status
1439359Dead
2479354Dead
3529234Dead

Smart Split Up Ruler
RunRaqueno-ReevesSmart Split UpEnemy Status
1499385Dead
2484343Dead
3455386Alive

Migrate, Gang Up, and Split Up Rulers
RunRaqueno-ReevesGang UpSplit UpMigrateEnemy Status
141527941421Dead: Migrate
26684733947Dead: Migrate
38773582751Dead: Migrate, Split Up

Download

JFreeChart: Open Source Charting Solutions

Posted on Monday, September 01, 2008
0 commentsAdd comments

JFreeChart is an open source chart library created by Object Refinery Limited, and may be downloaded from SourceForge.org. JFreeChart’s target consumers are Java developers looking to bring high quality, professional charts to their applications. The library provides a comprehensive collection of chart types, including pie, bar, line, area, scatter, and many others that when combined with JFreeReport provide Java developers powerful presentation tools.

Having used .NET reporting and charting solutions over the past several years, I chose to evaluate JFreeChart against the three prime directives of open source software (OSS) engineering. Specifically, I was interested in determining whether I would consider using a Java OSS charting solution such as JFreeChart over the .NET charting tool I have experience using, as well as, how similar or dissimilar it is to .NET charting tools. Some of the most impressive .NET charting tools I have seen on the market are Dundas Chart for .NET, The XtraCharts Suite by DevExpress, and integrated into its reporting tool Active Reports for .NET from Data Dynamics (ARNET). My experience is with the latter of these applications, which are all designed for developer integration into their applications.

According to Philip Johnson, Professor of Information and Computer Sciences at the University of Hawaii, and Director of the Collaborative Software Development Laboratory,

The three Prime Directives for Open Source Software Engineering are:

1. The system successfully accomplishes a useful task.The system does not have to include every bell and whistle to accomplish a useful task. Indeed, the art of incremental development is to determine the smallest useful increment of functionality and implement that first.
In most cases, careful thought, ample customer interaction, and efficient design and implementation can lead to a first customer release with a single useful function within weeks after project inception.
A system developer cannot verify that the system achieves PD#1. Only an external end-user can.
2. An external user can successfully install and use the system.The system must include sufficient user-level documentation to support download, installation, and use of the system without significant interaction with a system developer.
A system developer cannot verify that the system achieves PD#2. Only an external installer can.
3. An external developer can successfully understand and enhance the system.The system must include developer-level documentation providing insights into the design and development of the system that enable an external developer to understand and enhance it.
A system developer cannot verify that the system achieves PD#3. Only an external developer can.

Using these criteria, how does JFreeChart fare?
Prime Directive #1
I think JFreeChart does an excellent job of fulfilling this requirement. It does one thing, Java charts, well. It is on par with ARNET as to the myriad of charting types available, especially when it integrates with JFreeReport. JFreeChart provides an extensive demo library with over 14 categories of reports and over 100 charting examples. Searching the web for JFreeChart examples provided code listings of similar length and structure to that of ARNET. With JFreeChart’s ability to connect to databases, such as SQL and Oracle, it is a power charting library that has the benefit of being open source for developers seeking to push the library even further with their own ingenuity. An excellent perk to this is that JFreeChart is free. However, to effectively use the library a developer would likely invest in the Developer Guide which costs $48.75 for an individual license, $487.50 for a site license, and a $1,950 for a global site license, which is equivalent to purchasing ARNET. There is also a comprehensive JavaDocs API that supports developers using JFreeChart in their applications.
Prime Direct #2
I had a lot of issues installing JFreeChart. First, SourceForge.org has three separate zip files that need to be downloaded, including the JavaDocs Documentation. One download is the JCommon zip, which is a required library for several of JFree’s software. After unzipping the downloaded files, the directories contained the source code, but lacked the compiled versions. Unclear on how to proceed to install the library at this point, I searched for an installation guide from Google. I located one, which would have been nice to have as an actual download from SourceForge.org in addition to the compressed files. The installation guide stated that the source codes required a build using ant. That set off another search to acquire ant. From Apache’s ant website, I learned that ant should be contained in the version of the Eclipse IDE I was using, so I started up Eclipse. Once in Eclipse, I had to load the JCommon and JFreeChart projects using the “Java Project from Existing Ant Buildfile” option. Since JFreeChart required packages from JCommon, I decided to build JCommon first. However, the IDE had issues compiling the 181 Java source files. Attempting to resolve the compilation issues, I searched some more using Google. Eliminating some and creating others, I eventually gave up on trying to build the packages. So, I was unsuccessful in installing JFreeChart.
Prime Directive #3
Reviewing some of the JFreeChart source code revealed that it is well structured, adequately commented, and written in a manner I appreciate. I would find it easy to contribute to the existing implementation, understand how the library classes interact, and work on writing documentation for end users (Java developers).
Overall, I would consider using JFreeChart as a charting solution, in spite of the difficulty with installation. There are enough features and robustness that JFreeChart has that makes it worth the effort to resolve the installation issues. While it may not look as slick as Dundas’ charts or come already integrated into JFreeReports as is the case with ARNET, it seems to have all the same functionality and usability as these.

Subscribe to: Posts (Atom)