Sunday, October 18, 2009

Midterm Questions

1. What is the difference between locking and non-locking when talking about version control?

Locking only allows one person to check out a file and work on it. Non-locking allows multiple developers to check out the same file and make changes.

2. Name one advantage of non-locking over locking.

The problem of a user taking out a lock and forgetting to return the file by unlocking it is eliminated.

3. What is the difference between white box and black box testing?

In white box testing, a tester uses an internal perspective of a system to develop test cases based on the internal structure. In black box testing, a tester only has an external perspective of a system and chooses valid/invalid inputs and ensures the correct output is returned.

4. What is the difference between the Codeline policy of an Active Development Line and a Release Line?

For an Active Development Line, progress is slightly favored over stability. For a Release Line, stability is favored over progress.

5. List two distribution terms that Open Source software must comply with. Provide a brief explanation of each.

Free Redistribution - The license shall not restrict any party from selling or giving away the software as a component of an aggregate software distribution containing programs from several different sources. The license shall not require a royalty or other fee for such sale.

Derived Works - The license must allow modifications and derived works, and must allow them to be distributed under the same terms as the license of the original software.

6. Explain one reason that Open Source software has been successful and popular with developers.

Community - Having a common source code pool and the tools provided by the Internet creates an opportunity for extensive and speedy collaboration on development projects.

7. What is wrong with the following statement?
import java.util.*;

Using the “*” in an import statement is a violation of coding standards. You should explicitly import each class that you use from other packages because it is an important form of documentation for those reading your code.

8. List at least two things you should do before asking a technical question by email, newsgroup, or website chat board.

1) Try to find an answer by searching the Web.
2) Try to find an answer by reading the manual.

9. Does a high percentage in a coverage report ensure the quality of your code? Explain your answer.

No, a high percentage in a coverage report can expose code that has not been adequately tested, but it cannot guarantee the quality of your code. You need to ensure that your tests are thorough and adequate enough to ensure the quality of your code.

10. Why is it important to get developer buy-in when implementing coding standards?

It is important to get developers to buy-in when implementing coding standards so they understand the importance of the standards and are more likely to follow them. Providing the reasoning behind each rule can encourage adoption of the rules.

Thursday, October 15, 2009

Collaboration through SVN

Subversion or SVN is a version control system that is used when there are multiple developers that may be working on a project at the same time. This software ensures that everyone is working on the latest version of the project. Also, SVN is very useful when multiple developers are working on the same project because it can ensure that different developer's changes don't overwrite each other. SVN is non-locking which means that two developers can work on the same files at the same time. The files are checked for conflicts when they are committed. If any conflicts occur, the developer who is trying to commit is notified that they must update their files and resolve any conflicts before committing.

I was able to host my Robocode project on Google Project Hosting and create a discussion group for it. I found that setting up the automatic commit and issue messages to be difficult. At first, I could not get automatic commit and issue messages to be sent when changes were made to the project files. I added the group email address for the discussion site, robocode-kkc-diamondbot-discuss@googlegroups.com, to receive activity notifications. I finally got it to work after setting robocode-kkc-diamondbot@googlecode.com to be the sender.

I learned that using Google Project Hosting and SVN is a good way that multiple developers can collaborate on a project. It is vital to have version control when working with multiple developers to ensure that progress keeps moving forward. Attempting to accomplish this manually would be an extremely tedious and time comsuming task. Thankfully, there is version control software like SVN that can automate the process.

Monday, October 5, 2009

Passing the Test

Automated testing is an efficient way to ensure that as you develop a program it still works correctly and as expected. This approach is much more time efficient than entering test cases manually. As you add new functions to your program, it is important to ensure previous capabilities are not affected. JUnit is an automated Java testing program that allows a developer to create custom tests to verify functionality and performance.

As I developed my Robocode robot, it was important to ensure that changes I made while adding new features did not result in a loss of previous performance. I could have manually run Robocode each time I made a change, however, this approach is time consuming and takes away effort that should be put towards improving my robot's performance. JUnit allowed me to create tests that could be run in a fraction of the time it would take me to accomplish manually.

The three types of JUnit tests that were created that were acceptance, behavioral, and unit tests. Acceptance tests verify that a robot can consistently defeat another robot. Behavioral tests check that a robot correctly implements a movement, firing, or targeting strategy. Unit tests verify that individual methods correctly calculate an output for specified inputs. These tests can provide a developer a reasonable performance measurement. While this does not test for all situations, it can cover a substantial portion of your code to ensure that it is working as expected.

The simplest tests to create were the acceptance tests where a robot is matched against another robot to verify that it can consistently defeat it. I chose to battle my robot against RamFire and Crazy and check that it was able to win more than fifty percent of the time. The behavioral test was more difficult to create. There was much more information that was required to be gathered to validate that a strategy was being implemented. I decided to test my movement strategy. I ran into problems getting my behavioral tests to work correctly. Eventually, I was able to get this test to work. The unit tests that were created verified the output of three methods. One calculated a distance that was required, another calculated an angle, and the last calulated how many degrees the robot needed to be turned to face the next position.

Now that I have some experience in writing JUnit tests, I would develop my robot to have smaller methods. I found that I was doing too much in one method, which made it difficult to write tests for. I had to break down my methods without altering the behavior of my robot to be more specific to accommodate testing. After modifying my robot, determining how to perform unit tests became much simpler.

I felt that these tests adequately tested my robot since the program was rather short. If this had been a larger project, I would have had to write more tests in order to increase the coverage provided by the tests. Listed below are the results from running Emma.

Overall coverage Summary:
Class Percentage = 89%
Method Percentage = 80%
Block Percentage = 55%
Line Percentage = 56%

Even though I ran into some issues while developing my tests, I was able to see the value in creating automated tests. After the tests were created, I was able to run them over and over without much time and effort. The ability to create automated tests is an essential skill to have and is particularly valuable when developing a large project.

A distribution of my robot including JUnit tests can be found here.

Tuesday, September 29, 2009

Build Systems

Build systems are tools that can be used to automatically build your programs and perform automated quality assurance. They can be customized to perform many automated checks such as ensuring correct versions of software and necessary packages are installed. They are very flexible and users can customize them to meet the requirements of their project.

Ant and Ivy are good because they ensure that all users' and developers' systems are setup correctly before a program is executed. They can automatically download and install necessary software if they are missing. Also, build systems can inform users of problems such as incorrect software versions which may pose potential problems. They allow for cross-platform usage. Tedious tasks such as ensuring correct syntax is used when specifying paths are automatically handled by the build system.

Tools used for automated quality assurance such as Checkstyle, PMD, FindBugs, and JUnit can be applied to projects. Manually checking coding standards and best practices can be a very tedious and time-consuming task. Thankfully, these tools can automate the process and allow developers to concentrate on more important tasks. Although they cannot replace code reviews, they can ensure that formatting issues and coding standards are followed.

Checkstyle can help ensure that coding standards and best practices are followed. It checks the Java source code for things such as comments, naming conventions, and indentions.

PMD also provides assurance that best practices are followed. It can also find sub-optimal code and potential bugs. Like Checkstyle, it analyzes the Java source code.

FindBugs is a tool that differs from Checkstyle and PMD in that it analyzes Java bytecode. It searches for potential bugs that can break your program. This program searches for strings of bytecode that are known to potentially cause serious problems.

These tools can be incorporated into an IDE such as Eclipse to allow for feedback as the program is being developed. They will also create a HTML report containing descriptions of each problem found and their location.

JUnit allows developers to create simple tests to ensure that software is working correctly. Automated testing such as that provided by JUnit can save time and effort. It provides the developer some assurance that the program is functional without manually entering different test cases.

I found these tools to be very useful. They were able to find problems with my code much quicker than I would have been able to. They found two problems with my code. Checkstyle reported a problem with a condition in an IF statement I had declared. It reported that the expression (move == true) could be simplified. PMD reported a best practices violation in which I had variables that could be declared as local variables. After fixing these problems, I was able to successfully build my project.

I made some improvements to my Robocode robot based on observations made during the first robot battle. I restricted the range that my robot fires in order to save energy. I also attempted to adjust my firing to account for the many Walls style robots that were in the first tournament.

A developer distribution of my system can be found here.

Sunday, September 20, 2009

DiamondBot

Robocode is a fun, educational game where people can develop a virtual robot and battle it against other robots to see how effective it is. My first attempt at designing a competitive robocode robot was called DiamondBot. It was designed based on observations that I made during my review of sample robots that are provided with the robocode installation as well as the brainstorming of counter-robots for some of the sample robots. I tried to incorporate strengths and defenses for weaknesses that I observed into the design. The goal was to reliably defeat as many of the following sample robots as possible. The sample robots to defeat were Walls, RamFire, Spinbot, Crazy, Fire, Corners, Tracker, and Sitting Duck. Descriptions of my robot's movement, firing, and targeting are shown below.

Movement:
DiamondBot moves around the robot battlefield in a diamond pattern. The robot's movements change based on whether it is hitting its target or not. If it's hitting its target, then it will stay still if it gets close to the enemy. If the robot is missing its target, then it will try to stay away. If a collision with another robot occurs, the robot attempts to back away and continue with its normal movement pattern.

Firing:
DiamondBot varies the power of its bullets based on distance and accuracy. As an enemy gets closer, the power of the bullets fired increases. If DiamondBot is missing a lot, the maximum power of a bullet is reduced to prevent it from becoming disabled as quickly.

Targeting:
DiamondBot targets enemies by scanning with its radar and firing at the scanned position. If DiamondBot is missing a lot, it attempts to shoot an enemy by leading it to cause the enemy to run into the bullet.

DiamondBot was able to consistently defeat Walls, Ramfire, Crazy, Fire, Corners, Tracker, and Sitting Duck. However, it did not do well against Spinbot. I tried to come up with a strategy that could be used against Spinbot but, when making changes to compensate for Spinbot, I found that my performance against other robots decreased. I finally decided to sacrifice performance against Spinbot in order to keep performance against the other robots.

Creating my first competitive robot gave me insight into how difficult it is to create a well-rounded robot that is effective against many different strategies. When I made changes to increase my robot's performance against a specific robot, it often degraded its performance against other robots. It is very difficult to balance a robot, so it is always effective. I should have come up with a more solid, well-thought out strategy by doing further research on different strategies before starting to build my robot. I found that you must be flexible in your design because things don't always work out how you planned.

A packaged version of DiamondBot can be found here.

Tuesday, September 15, 2009

RoboReviews

There are several sample robocode robots that are part of the robocode installation. These robots show different strategies and options that robots can use. The sample robots provide a good way for beginning robocode programmers to learn how to control robots they build. Each of the sample robots use different techniques for movement, targeting, and firing. I will discuss the strategies used for several of the sample robots.

Walls:
The walls robot continually moves along the outer edge of the battlefield. This robot keeps its gun facing in and fires at enemy robots with medium power when detected. If there is an enemy on the next wall to travel, Walls waits at the corner and fires down the line until the enemy moves or it is destroyed. Walls uses an avoidance strategy if a collision occurs. The walls robot moves to the opposite wall that it was moving down when the collision occurred. This robot uses a simple, but very effective strategy. It has a good balance of offense and defense.

RamFire:
When an enemy robot is scanned, Ramfire moves towards the enemy and attempts to ram it. This robot only fires after it rams the targeted enemy. It determines the power of its shot based on the amount of energy an enemy has remaining. The more energy an enemy has, the stronger the shot. RamFire continues to shoot an enemy with bullets until it is weak enough that it can destroy it by ramming. This robot attempts to gain bonus points by killing an enemy by ramming it rather than shooting it. This robot's strategy is offensive. While it can get bonus points if it is able to kill an enemy by ramming, a robot that can avoid being rammed can kill RamFire rather easily.

Spinbot:
Spinbot continuously moves in a clockwise circle and fires when an enemy is found. When this robot collides with another robot, it attempts to determine who's ramming into whom. If it determines that the collision was its own fault, it moves away from the enemy and continue its circular movement. If not, the robot fires at the enemy that collided with it. This robot always fires strongly regardless of an enemy's distance. This robot has a decent defensive strategy for avoiding bullets, but its targeting isn't that good.

Crazy:
Crazy uses an interesting strategy. It moves in an alternating arcing pattern. If a wall is hit or if it hits another robot, the robot reverses direction and continues with its arcing pattern. The Crazy robot fires weak bullets at scanned enemies. This robot mainly relies on its semi-unpredictable movement to avoid being shot. Attempting to make movements random seems to be a good defensive strategy.

Fire:
The Fire robot determines how much power to use when firing based on enemy distance and its own remaining life. If the enemy is within 50 pixels and it has more than 50% life, it fires a strong bullet, otherwise, it fires a weak bullet. The Fire robot sits still until it is hit by an enemy bullet. At that point, it changes its heading between -180 and 180 degrees based on its current heading and a scanned enemy's heading. Then, the Fire robot moves forward or backward a specified distance, alternating direction after each time it is hit. If the Fire robot is rammed by another robot, it faces its gun to the enemy and fires strong shots at it. This robot has a decent defense strategy to avoid enemy fire, however, its targeting of enemy robots is not that good.

Sitting Duck:
On the surface, the Sitting Duck robot seems to do nothing. However, it actually keeps track of how many rounds and battles it has been involved in. It displays this information in the console. This just shows you that you can't make assumptions about code based on behavior. You need to actually read the code to know what is happening.

Corners:
The Corners robot moves to a chosen corner, being careful not to crash into another robot while it is on its way. If Corners sees an enemy while it's on its way to a corner, it stops and fires at it. Once it gets to a corner, it turns its gun back and forth until an enemy robot to fire at is scanned. Corners determines the amount of power used based on its distance from the enemy and its own life. If the Corners robot is far away or its life is low, it fires a weak bullet. If Corners has a decent amount of life remaining, it increases its bullet power as an enemy gets closer. This robot uses a good strategy to determine the bullet strength used.

Tracker:
Tracker finds a target robot and attempts to follow it. If Tracker loses an enemy and cannot locate it within two turns, it searches by turning its gun to the left 10 degrees per turn. If it cannot find the enemy within five turns after losing it, it turns its gun right in increments of 10 degrees. If it still cannot find its enemy after ten turns, it looks for another enemy to target. Tracker attempts to get within 100 to 150 pixels of the target enemy. If it is too close, less than 100 pixels away, it backs up so it is within the 100 to 150 pixel range. Once a target is in range, it fires a strong bullet at it. If tracker collides with a different robot from the one already being tracked, the enemy robot that collided with it becomes its new target. Then, Tracker fires at it, and backs up a little. When Tracker wins a round, it does a victory dance. This robot employs a good tracking strategy. However, its defense is not that great because it can be getting shot by other robots that it is not tracking and it won't retaliate.

By reviewing the sample robots, many things about different strategies' strengths and weaknesses can be learned. Using the knowledge gained, I hope to incorporate the strategies that I found effective to build a competitive robot.

Sunday, September 13, 2009

Coding Standards

Coding standards are a set of guidelines that programmers follow in order to make their code easier to read and understand. These standards involve things such as formatting, naming conventions, and documentation. Code is easier to read and understand when it is in a format that is familiar. Coding standards are also useful because the majority of code that is created will be read and modified by many different people.

Reading and understanding code that is written by someone else can be a difficult task. Writing code conforming to standards helps make it easier. The use of meaningful comments that explain difficult or essential parts of a program can speed up understanding a lot. On the other hand, having poor comments and bad formatting can make understanding nearly impossible for large, complex programs. Making code as easy to read and understand as possible should be done as a courtesy for the next person who has to work on it.

There were three coding standards that were implemented for the Robocode project. Each of the standards provide useful guidelines that make code easier to read and understand. These standards are listed below.

1) Elements of Java Style
2) ICS Coding Standards
3) ICS Robocode Standards

Upon review, I found that my code was not conforming to some of the standards for this class regarding formatting and documentation. One violation I found was that I was using tabs for indentation rather than two spaces. At first, I thought that it would be very tedious to change the formatting of my code to conform to the standard. I was glad to discover that the formatting of my code was easily fixed with the use of the provided XML file. I also added documentation comments to my code so others who read my code will know the purpose of the code at a glance.

The .jar file containing my code can be found here.