Wednesday, December 9, 2009

Final Thoughts on ICS 413

Today was the last official class meeting for my software engineering class, and as a final assignment, we were asked to write a blog post summarizing our thoughts on software engineering and the course in particular.

I started the class not knowing what exactly software engineering was, but being excited about the opportunity to work with others to develop code. In all previous classes, we received very stern warnings that we were not to work with others on homework assignments, so I developed a very strong mentality of programming everything on my own with only minimal conversations between my classmates and I regarding our code. As a result, I took the class wanting to see what it was like to program with others.

Throughout the course, I've learned that software engineering is a complex process, but that there are many tools available for programmers to use to help them do software engineering with the least possible pain. Before the class, I didn't know how complicated it was to share a project with new developers; nor did I anticipate how difficult it would be to have two people working on the same programming project. Among the tools that we learned in class were JUnit, to test the code for constant functionality; Ant, to standardize the development environment; Subversion, to facilitate sharing code; and Google Project Hosting, to provide hosting for the project code and a way to track issues on the project. All of these tools were difficult to learn or get used to at first, but once I got a basic understanding of them, they definitely made group work a lot easier.

I think that one of the most important aspects of the class for me wasn't necessarily the programming experience, but the development of a professional person that I can use to present myself to graduate schools and prospective employers. This includes not only the programming and software engineering skills that I picked up on in the course, but also my professional portfolio and this blog. These are both items that I will be able to continue to update and to use to present my programming skills and my knowledge of software engineering.

This class was a lot of work, and I definitely spent more time working on assignments for this class than for any of my other courses this semester (and possibly any of the other courses in my undergraduate career). However, because of this, I feel that I have a much better understanding of what is involved in the creation, development, and deployment of a programming project. I now know how much time is involved in the process and I know of the tools available for use to facilitate software engineering. It was a tough experience, but it was a good experience to have had.

Eco-Depot version 2.0

As the final project for my software engineering class, my group and I worked on improving the design and increasing the functionality of the Eco-Depot web application, as discussed in my last few blog posts. This involved going back to our previous implementation to make it more user friendly while adding additional features to the system.

For those of you who have not read my previous posts, Eco-Depot is a web application that seeks to provide information to users on the state of the Oahu power grid, based on the WattDepot system. This is done by analyzing the ratio of carbon versus energy produced, so that Oahu residents can reduce their carbon footprint on the environtment. Additional features for version 2.0 allow users to easily access information on the amount of energy produced by the grid. The application seeks to provide energy consumers with the information that they need to become smart consumers. As a side note, the WattDepot system currently uses simulated data for the grid.

One of the main problems with our version 1.0 implementation is that it was not designed with an ordinary user in mind. It had very few instructions, no obvious purpose, and had a very bleak look and feel. One of the main things that we tried to do for version 2.0 was to make it easier for an average user to understand and use the site. This was done by adding in a main page with an introduction to the system, as well as providing additional information on pages with functionality. We also included more graphics (all made by Kendyll) and used CSS to provide a standard look and feel for the page.

The second major item that we needed to accomplish for version 2.0 was to convert our table of carbon content data into a stoplight to display only the current analysis, as well as to write a second page that would allow users to see the energy produced by any of the Oahu power sources over a specified period of time. Most of these items were not extremely difficult to do - it was all of the background work that took a long time to understand. In particular, we had to wrestle with understanding and implementing sessions for the pages so that multiple users would be able to use the application without inadvertent sharing of the information between the two. Additionally, we experienced problems with Wicket because of our lack of experience working with the language.

Overall, I learned a lot about Wicket from working with this project. Also, and perhaps more importantly, the entire web application creation process gave me a better understanding of software engineering and the effort that it takes to program something with a team of people rather than alone. One of my group's biggest problems was generally communication - communication about what we were working on, communication about what we needed help on, and communication on what everyone else needed to do so that everything would come together smoothly. Although we used the Issues management feature of Google Code, sometimes we ran into problems where one developer's item relied on things being written by another developer, but the two pieces needed additional work in order to communicate together. As we neared the project due date, I feel that we were a lot better about communication because we had all realized that we needed to constantly keep in touch so that everyone would be able to work on something at the same time with minimal clashes.

Our completed product can be downloaded for use as a Java jar file, and with the complete code in a zipped distribution file on the project's Google Code Downloads page. Additional information on the product and its development are also available on the project's page.

Tuesday, November 24, 2009

Reviewing the Greendepot Wicket Web Application

The application that I worked on as described in my last blog post was a class project in which each group of 3-4 members created their own application. Here, I present a coding review of the Greendepot web application, which can be found on Google Code here.

My full review of the project can be downloaded here, but in this blog post, I would like to make comments on a few key points regarding the project.

First of all, the application just needs a bit more time and work. The main thing is that results are printed on the command line, rather than on the web page. This is one thing that definitely needs to be cleaned up before the next version release, as it is not very user-friendly. Additionally, although it provides the carbon content for each hour for a day, it does not analyze the actual numbers to say if it would be a good idea to use electricity at a specific time or not.

Second, I found one area in the code that would be worth considering refactoring. This is the setDate method in the CarbonCalculator class. Briefly, this method seems to do a lot more than its name implies, so at the very least the method name should be changed, although I think it would be best to split up the tasks done by the method. Rather than setting the date, creating a list of data, and saving the string of data (for output purposes), it would be better if these three tasks should be split into three separate methods.

Finally, in regards to Continuous Integration, I would like to make the point that the Hudson build for the greendepot project does not seem to be executing any Ant tasks when changes in the code are detected. This is important for monitoring the project and should be fixed as soon as possible.

Again, these are the two main problems that I found. Please refer to my full review, referenced above, for complete comments.

Monday, November 23, 2009

Introducing Eco-Depot!

For my software engineering class, this past week has involved working on another aspect of interaction with the WattDepot client. Whereas before we focused on creating a command line interface for the system, this past week we began to look at designing a web application for it, which is intended to make the system more user-friendly and accessible to the general public. In particular, we were to design a web application that would take a date as input, and output a table showing the carbon content of the simulated Oahu grid per hour, analyzing if the carbon output is low, medium, or high. My group chose to name our project Eco-Depot.

This time, we got assigned to groups of four for the assignment, generally with two pairs being put into one larger group. At first, it was pretty difficult for me to work with a larger group. One thing was definitely the fact that we did not meet face-to-face much, and were not consistent with virtual communication. As a result, we ended up with a few instances of group members not realizing that tasks had not been completed, or group members wondering exactly what they were supposed to do.

My main task for the development of the web application was to write the Java code for the main interaction with the WattDepot client. The hardest part of this was anticipating what would be necessary for the people who were mainly writing Wicket. To tackle this problem, I first tired to extend the command line interface that Kendyll and I had written last week, but found that I was second-guessing myself, especially when trying to add things to the Wicket application. As a result, I wrote several key methods, let my team members work on it, then looked to that for feedback on what else I needed to write. The biggest disconnect that I noticed was when they used arrays to handle working with data, while lists were the most convenient data structure for my end of the programming.

Overall, I think that although my group got the assigned task done, we could have worked better together. The main thing that I think we needed to do was to communicate better; Kendyll and I had a good system of relying on Google's chat to talk while we were programming, and we knew that we would check our e-mail multiple times a day, but this didn't seem to be the case for our other two group members. Getting things like this straightened out from the start probably would have saved a lot of hassle and last-minute worry on our part.

Here is the ICU for our Eco-Depot project over the last week:

As you can probably tell from it, we did most of our coding over the weekend. I think this is an indication of an increased workload for all of our classes as the semester ends. Personally, I simply didn't have the time to dedicate to the project until the weekend because of projects and a take-home midterm due throughout the week.

Our initial version of the code can be downloaded from Google Code here. Please refer to the Wiki page for additional information regarding the use of the product.

Monday, November 16, 2009

WattDepotCLI Version 2.0: A second look at the system

Over the past week, I have worked with my partner to implement a version 2.0 of the WattDepot CommandLineInterface that we have been working on for approximately three weeks. This process involved taking the comments from the code review completed a week ago, and incorporating the appropriate updates to the code, in addition to creating implementations for three additional methods.

The main comments from the code review basically said to just spend more time on the project to add more functionality, so this was one of my main focuses for the week. I implemented test cases for the commands that I had originally implemented, and I also split up all of the files into two separate packages, to separate the parsing of commands from the methods to carry out those processes. The test cases took some time, but I found that once I got the general structure of one completed that it wasn't as difficult to implement additional test cases for my methods after that. As for the reorganizing of files, I really took advantage of the Refactoring tool in Eclipse to make it a quick and painless process. Also, one item that we didn't get in our code review but that concerned us was the consistency of our code. We worked to refactor some methods so that the method signatures would have a similar style.

I did not regularly meet in person with Kendyll to work on the code since we both had busy weeks with our other coursework, but we kept in touch with each other regularly via e-mail and instant messaging. This worked well because we were able to work on our own time when we had the chance, but also always had an idea of what we were supposed to be working on at all times. We tried to partition the workload evenly, but found that at times we were setting it up where one person would work on the code for a while, make a commit, then let the other person work for a while, just because our schedules didn't allow for a more consistent division of work at all times.

As part of the adaptations we made for version 2.0, we also began using the Hackystat ProjectBrowser to monitor the "health" of our project using nine different key areas. The overall ICU for our project over the past week is:



For the most part, you can see a trend in increasing coverage and decreasing complexity, which are both signs of a healthy project. From this image, you can see that there is a clear increase in work done as time progressed, which occurred because both Kendyll and I were busy for most of the week and had to wait until the weekend to get work done, although we both tried to do some minor work on the system each day. Probably the only thing to really worry about from the ICU was the trend in coupling, which indicates that our files were becoming more tied together. I believe that the increase was caused by the fact that many classes either implement or extend other classes, and we could not get around this

I would like to address the "churn" factor, which looks ridiculous at first glance. The reason it is so high is that I did not refactor the system into different packages until yesterday. Thus, the system registered this as hundreds of lines of code being deleted and hundreds of lines of code being written in one commit, when it really only involved files being moved around. If you exclude this day

Finally, we were asked to use our system to generate the answers to several commands. Kendyll did this part, so please refer to his blog post for the full details. However, the answers were:
  • What day and time during the month was Oahu energy usage at its highest? How many MW was this?
    >power generated SIM_OAHU_GRID timestamp 2009-11-26T20:00:00.00-10:00
    4.96E8
  • What day and time during the month was Oahu energy usage at its lowest? How many MW was this?
    > power generated SIM_OAHU_GRID timestamp 2009-11-28T02:45:00.000-10:00
    9.95E2
  • What day during the month did Oahu consume the most energy? How many MWh was this?
    >powerstats generated SIM_OAHU_GRID day 2009-11-26 sampling-interval 60 statistic max
    9.95E2
    What day during the month did Oahu consume the least energy? How many MWh was this?
    >powerstats generated SIM_OAHU_GRID day 2009-11-26 sampling-interval 60 statistic min
    4.93E2
    What day during the month did Oahu emit the most carbon (i.e. the "dirtiest" day)? How many lbs of carbon were emitted?
    >total carbon generated SIM_OAHU_GRID day 2009-11-04 sampling-interval 60
    29959
  • What day during the month did Oahu emit the least carbon (i.e. the "cleanest" day)? How many lbs of carbon were emitted?
    >total carbon generated SIM_OAHU_GRID day 2009-11-07 sampling-interval 60

    22908

My group's completed version 2.0 can be downloaded from Google Code here.

Wednesday, November 11, 2009

My Code Review Experience

My software engineering class implemented a code review over the past week, to help each of the pairs get feedback on our implementation of the WattDepot command line interface. A code review is a systematic examination of source code intended to find mistakes overlooked in the development phase; it improves both the overall quality of the code, and the skills of all developers involved in the review.

I was assigned to review two other systems. In doing this reviewing, I noticed several things that could be implemented or improved in my own system. For instance, I found a way to break one system (by putting in an incorrectly formatted timestamp), and I knew that the error was not caught in my own implementation. I also found more efficient ways to do things, such as creating a method to check that a timestamp was correctly created, since this is something that almost every method executing a command requires.

On the side of the coder whose system was reviewed, I received good feedback from all four of the reviewers. The basic message from all of them was that the code that was already written was good, with a few minor things to fix, and that mostly we needed to continue working on the code to implement test cases or to refine error messages. I also got some good feedback on errors that we need to catch because they currently cause the system to stop working properly.

Overall, this code review gave me a lot of ideas on things that we can improve in our system, and I think that we'll be doing a lot of improvement in the next five days before version 2.0 of our system is due.

Saturday, November 7, 2009

Code Review of WattDepot-CLI Branches

After spending the first half of last week working hard to finish our version 1.0 of the WattDepot command line interface, my software engineering class took a break of sorts from straight programming to conduct a code review for our various branches of the code. We were each assigned two other implementations to review, meaning that each group would receive feedback from four or five other people. I was assigned to review the Elua and Eha branches of the project.

To conduct this review, each of us used the template that was provided by my teacher. Essentially, I went through the code, first ensuring that it compiled and passed the automated quality assurance tools and doing basic testing. After that, I looked through the JavaDocs for the code, as well as the code itself, to determine if there were any additional problems.

My full reviews for the two branches can be found here:

I will be giving a few of the main points for each branch here, but if you are interested in my full comments, please refer to the PDF files linked to above.

Elua branch
Overall, I found few major problems with this branch. All of the commands work, although some fine-tuning is in order to ensure that there are no problems with incorrect commands being accepted. I would say that the biggest area for improvement is in the JavaDocs, some of which are missing @param or @return tags, and all of which would feel vauge to a new user of the system. Testing of the branch was thorough, although it would be a good idea to test one or two of the cases in which errors occur, since this is the main reason for lack of coverage by the tests provided.

Eha branch
This system worked well, but I feel that there are two major points that would benefit from additional work before future versions are released. First of all, the organization of the classes and methods could use some work. As detailed in my comments, the UserCommandInterface class should be broken up into several new classes, based on the type of command being called. Second, the test cases could use improvement, as they check the handling of correct vs incorrect input, and not the actual information that is output by the system.

Wednesday, November 4, 2009

Group Work Time! The WattDepotCLI

As my software engineering class enters the second half of the semester, we have begun work on the WattDepotCLI. WattDepot is a service that seeks to collect data on electricity so that the data can be later used for visualization tools and analysis. My class also began to work in pairs for this assignment, so I had to also take advantage of tools like Subversion and Hudson, as discussed in earlier posts.

The assignment to implement a command line interface (CLI) for WattDepot turned out to be a lot more intensive than I had originally expected. The WattDepot library includes an API, and this was helpful once I really got into writing the necessary classes and methods for the CLI, but it was daunting to just begin the project.

Also, I feel that we didn't have a good design strategy in place from the beginning of the project, which meant that for several days we were stuck on how to write the code, and that we were left with several major changes to make to the project. One of these was implementing commands by creating an interface and using a Map to match commands with instances of the interface. I feel that I'm somewhat rusty in using Java, since the last Java-focused course I took was well over a year ago, so these ideas took some time to figure out.

Finally, this was the first time that I've really had a need to use Ant's verify command to do automated quality assurance. For the most part, I've only had to deal with Checkstyle, and rarely, if at all, FindBugs and PMD. With this project, though, I found it really frustrating to make all three tools happy. The worst case of this was when PMD told me to combine multiple lines into one, which would have made for a line of code that would have been close to 300 characters - definitely outside of the range that Checkstyle will allow! Although the tools were useful, it was sometimes difficult to satisfy the tools while trying to upload a file that was partially but not quite completed, and that still had minor errors that PMD or FindBugs would complain about. In this sense, I feel like it almost inhibited my productivity, because I was constantly having to go back and hide code with comments, just to satisfy one of the tools.

Working with a partner was a new experience in my career as an ICS student at UH. In all previous classes I've taken, we were told to not work with others on any assignments, and all assignments were relatively small and self-contained. Thus, it was very different to have to schedule meetings and coordinate roles in the group. Kendyll and I switched back and forth on how to break up the list commands. First, we decided to break it up by type (Power, SensorData, etc.), then we broke it up by subtype (day vs timestamp) and finally switched back to the first idea.

While Kendyll and I technically finished the entire command specification for the assignment, there were several items that we wanted to complete but didn't have time to do. The one major part of the project that Kendyll and I were unable to complete were the test cases. Although I believe that our methods were designed correctly to facilitate testing, we just ran out of time to write the test cases. The other thing that I didn't have time to do was to break up the command line processing and the methods themselves into two different packages.

Overall, I felt somewhat rushed and unprepared for the assignment in general. That being said, I did enjoy getting the chance to work on a project with someone else and on a project with real-world implications. I'm looking forward to getting the chance to explore the WattDepot project further.

My completed project can be found on Google Code here. Select the Ehiku version.

Monday, November 2, 2009

My Introduction to Continuous Integration

As my software engineering class moves on to the second half of our semester, we have begun focusing on working in groups to efficiently build a new program, the WattDepot Command Line Interface. The details of this project will be discussed in a future blog post over the next few days, but here I wanted to address the idea of Continuous Integration, which is a tool that we are using to facilitate our teamwork.

Continuous integration is a software development practice where team members integrate their work frequently, to decrease the time required for integration at the end of a project. This usually involves team members updating at least once a day, if not more often, leading to numerous integrations by the team each day. In addition, each integration is verified by an automated build that detects errors and notifies the developers of these errors as soon as possible.

For my class, we are using Hudson as the tool to facilitate continuous integration. During the Hudson setup, you can set it to poll for SVN updates with a specific frequency, and build the project each time there is an update. My project is hosted within Google Code, so I have Hudson check the site every five minutes to see if there is an update. Additionally, Hudson is set up to e-mail the relevant Google Group when there is a failed build; ideally, Hudson would also e-mail the developer that broke the build, but the functionality was not working when we tested in last Wednesday.

In class, I tested Hudson by building the project manually, committing a small change and ensuring Hudson noticed the change and built the job, as well as breaking the build and seeing if the appropriate e-mail was sent. Overall, I feel that Hudson was a little tedious to set up and that this would have been very confusing if not for my teacher's walkthrough of the process. However, since this is a one-time time cost for the project, it was worth it. Even though I tried to run the ant verify before committing my changes through SVN, a few minor errors still slipped through the cracks (for instance, making all changes for Checkstyle and forgetting to run verify again, which would have caught my error in not updating references to a method I had renamed).

Although I have not yet completed my project, I can already see the advantages of Continuous Integration, because it makes it easier to catch issues quickly. Also, Continuous Integration encourages me to always keep the project in a working state, because I don't want Hudson to have my project flagged as having a failed build for long periods of time. Other than the setup time involved (which was maybe about 30 minutes to ensure everything was working properly and was just a bit confusing), I see no immediate disadvantages to using Hudson. I'll continue to use this tool throughout the semester and will be refining my observations about it.

Monday, October 19, 2009

Midterm Study Questions

My software engineering course is having a midterm on Wednesday, and in preparation, my teacher assigned each of us to write 10 possible questions, similar to those that we should see on the midterm. These questions are related to the screencasts and reading assignments we have been given so far in the semester, all of which are detailed in the course's schedule. Answers are included with the questions.

Here are my study questions:
  1. What is the value of using the FizzBuzz program as a test of programming skills?
    The FizzBuzz program is not a good tool to find good programmers because by nature it is a simple program; it is best used as a tool to weed out people who can't program.

  2. What are some reasons people give for not using an IDE? What are some reasons for using an IDE?
    Reasons against: They are complicated to learn how to use and slow to master - you can't just write a program in your first five minutes of using an IDE; they take longer to load on a computer. Reasons for: They provide many tools, including compiling, refactoring, debuggers, and the ability to step through code; it makes it easier to understand, correct, and improve large software systems; it makes you a more attractive job candidate; makes it easier to work on large projects.

  3. What are some of the differences between IDEs and build tools?
    IDEs provide tools for code writing, incremental compiliation, and testing; and are developer-specific. Build tools provide support for compiliation, testing, packaging, and automated quality assurance; are project-specific.

  4. If you are trying to use an online forum to get help on a problem, what are some steps you should take before making a post and why?
    First, search for answers in manuals, online, and in forums. You should ensure that you are posting in a forum that is related to the content and level of your question so that it is not ignored. Also, you should give as much information in your post as possible, so that answerers will not have to waste time extracting information.

  5. Why does multitasking decrease overall productivity?
    Your brain becomes more focused on managing multi-tasking, than on the various activities that you are trying to focus your attention on. It also takes longer to switch between tasks.

  6. Why should you not rely only on coverage reports when writing tests for a program?
    Just because something was tested once doesn't mean that it will always work. Also, other problems may exist, such as code that does not do what it was originally supposed to or coding style violations.

  7. What is the main difference between white box testing and black box testing?
    White box testing looks at the inner workings of the code - it sees how input is converted to output. Black box testing only checks the input with the expected output, and often preforms functional tests.

  8. When using software configuration management on a team project, what are at least two things you should do in regards to creating branches of your code?
    Branch only when necessary, including when two groups need to work on code using different policies for updates; branch as late in development as possible to minimize changes that need to be propogated between branches; branch instead of freezing a codeline.

  9. What are the differences between Checkstyle, PMD, and FindBugs? What implications does this have toward your choice in automated quality assurance tools?
    Checkstyle is most useful towards checking coding standards, such as placement of whitespace and use of tabs. PMD also deals with coding standards, but will also catch issues like unreachable code or unnecessary statements. FindBugs runs the program and looks for runtime issues or ways to improve the run of the program. Both Checkstyle and PMD work with the source code itself, whereas FindBugs deals with the compiled byte code. Essentially, this means that using all three tools together is a good idea, since they each check for slightly different things.

  10. What is the main idea behind copyleft? How do copyleft software, free software, and open source software differ?
    Copyleft gives everyone permission to run the program, copy the program, modify the program, and distribute modified versions. However, it does not give the persmission to add restrictions to the software. Unlike free software, where people can create a proprietary modified version, users cannot create proprietary versions of copyleft software. Open source software cannot place any restrictions on distributed versions.

To my fellow classmates: good luck with the studying!

Tuesday, October 13, 2009

Robocode Project Hosting: "You've got mail!"

As the final element to the Robocode battle-robot building project that I have been working on for the past month for my software engineering course, I utilized Google Project Hosting to make my code easily available for revision. Throughout all of the assignments, my classmates and I have run into problems accessing eachother's code, and it has been an inconvenience to make a small change to a file, re-package the file, and then upload it again. This assignment sought to solve some of these problems.

I began working on the assignment by downloading a Subversion client. Subversion (SVN) is an open-source version control system, which manages files and directories over time. It keeps track of files and directories, allowing for multiple users to edit a file system, and to make it possible to always go back to a previous version of the system. The advantage to this in terms of working on programming projects is that Subversion will allow multiple programmers to work on a set of files, while doing the work to keep all of the files for all of the programmers up to date.

I chose to download TortoiseSVN, which is a version control software for Windows. It uses subversion to manage files that can be downloaded from a repository like the one available through Google Code. After downloading and installing TortoiseSVN, I was able to use it to log in and checkout a sample project from my instructor. This process means that I downloaded the code for the project with the ability to update the files in the original repository. (On the other hand, if I had merely wanted to view the source code, I could have checked it out anonymously.) I made a small edit to the downloaded code, then comitted my change so that it would be made publicly available for future users.

After getting the hang of using TortoiseSVN, I then endeavored to create my own project on Google Code, to make the code for my Robocode robot, PacerEvader, easily available for other programmers. I also created a Google group to discuss the project. In practice, this was not particularly necessary, as my robot is more or less completed, and it was an individual project. However, I can see many advantages if a programming project was worked on by a group of programmers. This is because it would be easy for all members of the group to maintain an up-to-date file set and to distribute any changes that he or she made.

I ran into one major problem while using the Google tools to manage my project, and that was in linking my Code project with the related Group. The Google Code site has the ability to send an e-mail to a single specified e-mail address whenever a change is made to the site, and the Google Group has the ability to receive posts via e-mail. Together, they seem to match up perfectly, except that I have not yet been able to link the two together. This is due to a reported bug that exists, where Google Groups does not allow the e-mail address that Google Code uses to send e-mails (more information on the issue here). New projects have an updated, working address that is used, and I have currently filed a request for the e-mail address used by my Google Code project to be updated, but as of now (October 13 at approximately 12:30pm HST), this issue has not been resolved. I have verified the set-up of both my Google code project and my Google group, so the e-mail notifications should work once the project is updated. (10/13, 4:30pm edit: My project was updated so that it sent from a new e-mail address accepted by Google Groups. I have since verified that the Google Code project will post to the discussion group when changes are made to the code.)

Wednesday, October 7, 2009

Robocode Editing - Testing Tools

Writing a program that compiles is relatively easy. Writing a program that does what it is supposed to and consistently generates the expected results is a much more difficult task. Luckily, there are a variety of tools available to help programmers utilize test cases to verify results and to verify that all test cases have likely been used. In the case of my software engineering class, these tools are JUnit and EMMA.

To address the issue of efficiently implementing test cases, I used the JUnit testing framework. This involved writing a number of Java test files. Unlike the test files I have written in the past, which typically involved defining a new object, giving it simple properties, then using print statements to verify that I got what I wanted, these test files would do the checking for me. JUnit will perform the actions or calculations I want, and then compare the results to what I expect, and let the test either pass or fail, depending on the results of the comparison.

Before, I begin, if you would like to reference the files I discuss, the distribution file for my newly updated and tested version of PacerEvader can be downloaded here.

There were three basic categories of tests that I had to do for my software engineering class: acceptance, behavioral, and unit.

In the acceptance tests, I verified that my robot would be able to beat two of the sample robots at least 60% of the time. This verifies that my robot is accomplishing its overall task of winning. I found that these were the easiest tests to implement because I did not have to alter the code for PacerEvader in any way - my working robot was simply placed in a battle with the sample robot that I set. I had to do a check only at the end of the battle, when I ensured that PacerEvader was the overall winner, and that it won at least 60% of the battles.

For the behavioral tests, I verified the movement strategies that I wanted to have my robot implement; namely moving to the top of the battlefield to pace back and forth, and moving to another wall when it hit another robot. These tests were more difficult for me to implement because I had to check properties of my robot after each turn, overriding the onTurnEnded method. This was not only tedious, but I also had trouble figuring out how to use the TurnEndedEvent properties to get details on my robot, as it required calling numerous methods to actual get a Robot object with all of PacerEvader's information. Because of the difficulties I had here, I was only able to complete two of the three tests I had wanted to, so I am one test case short of the required six for my software engineering requirement.

Finally, in the unit tests, I sought to verify that my robot fired using a power proportional to the distance it was from the enemy. This, by far, presented the most problems because I could not find a way to actually access PacerEvader's methods. I had first refactored my code to place the firing power calculation in a separate method, so that the value would be easier to check. However, since I could not access PacerEvader's methods, the only work-around that I could find to somewhat verify the calculations were correct were to copy my calculateFirePower method from PacerEvader into my JUnit test file and reference it from there.

In the process of testing my robot, I actually found a flaw in my implementation of the strategies for my robot. I intended to have my robot fire with power proportional to the distance from the enemy, but I left out an expression in the equation, such that it was almost always firing at maximum power. I did not realize this while looking through my code on my own, but double-checked the calculation when my test continually failed. I made the appropriate adjustments, then ran JUnit again to confirm that the change in firing power did not throw off any of the other results, the acceptance tests in particular.

After I completed my test cases, I used EMMA to analyze the coverage that my test cases provided. For the most part, I can feel satisfied with the results, given that this was my first time designing test cases for a program. All of the tests had block coverage above 70% and line coverage over 80%, aside from my main PacerEvader.java, which is not directly run since it is not a test file. (The fact that PacerEvader was not run significantly brought down the overall coverage for the package, so I am choosing to omit the overall summary.

Overall, I feel that I can still improve my test cases to truly ensure that my robot is successfully implementing the strategy I designed for it. To do this, I will need to find an easy way to monitor my robot's scanning and firing from within JUnit, because I could not find a way to check either of these. If I can accomplish this, I will feel much more comfortable with the JUnit quality assurance. I'm not sure if I could further redesign my robot to make testing easier since I am not sure of what will be required to hit the remaining test cases that I want. Through this process, though, I did realize that testing is much easier if you design the code toward it from the beginning, rather than trying to add in testing in the middle of project development.

The distribution file for my newly updated and tested version of PacerEvader can be downloaded here.

*Minor update to distribution file to correct a spelling error in one of the Java test files. The corrected version can be found here.

Wednesday, September 30, 2009

Quality Assurance: Robocode Improvements

For approximately the last month, I have been working with the Robocode project, which has me creating battle robots in Java. Initially, this project development was a completely individual assignment, where I programmed robots that were designed to run only on my computer. However, during the code review we did in class a few weeks ago, this design flaw was exposed when my partner had an extremely difficult time getting my robots to work on his computer. One of the solutions to this problem is the Ant build system combined with the Ivy dependency manager, which together not only include tools to put together projects for distribution, but also includes quality assurance tools that can be used check that files have the correct formatting.

In the past week, I have installed the Ant system on my computer, and used it in conjunction with Ivy to improve my PacerEvader robot that I had designed for the class Roborumble. The first thing that I did was to adapt the Ant code that my professor provided the class with for use with my robot, and then used the Checkstyle, PMD, and FindBugs quality assurance tools to check my code. Each of these tools does slightly different tasks, ranging from formatting, to analyzing the way code works, so it was important to run each of them. In total, the tools found 34 errors, with the following breakdown:
  • Checkstyle - 31 errors
  • PMD - 3 errors
  • FindBugs - 0 errors
The Checkstyle errors were all formatting errors, mostly dealing with a lack of white space. For instance, the following line of code:
fire(minPower+(maxDist-dist)*(maxPower-minPower));
initially returned 8 errors, because I had no whitespace preceeding or following each of the operators. I fixed it to read:
fire(minPower + (maxDist - dist) * (maxPower - minPower));
The PMD errors were slightly higher-level and included unnecessary return statements in functions.

I found that automated quality assurance tools are extremely useful because they provide an easy way to check formatting so that you don't have to worry about catching every little error while programming. I think that this would be extremely valuable if I got into a programming zone and wanted to write code without having to constantly worry about the formatting or optimizing my code. However, since these errors do need to be fixed eventually, it is advantageous to try to control the number of errors that these quality assurance tools would generate.

In addition to fixing the problems found by the quality assurance tools, I also created a basic junit test case for my robot, to ensure that my robot beats SittingDuck. Again, this utilized Ant and Ivy to run the test itself and check the results.

Finally, I made a small improvement to my robot's performance and prepared a new distribution file. The improvement was to add in another case where my robot would move to the opposite wall. My robot moves ahead and backwards along a wall, and if it is hit from nearly directly in front or from nearly directly behind, it will move to the opposite wall. This is to prevent the robot from getting caught in the first of a Walls-like robot that peeks ahead and continues firing until the wall it wants to move across is cleared.

My updated PacerEvader robot can be found here.
The distribution file for the robot can be found here.
Updated distribution file (10/5): here.

After completing this assignment for class, I am beginning to really appreciate the value of Ant. At first, I was skeptical about how much it would truly do to help me, but after completing this assignment, I see that the power is not only in its features for a build system, but also in its integration of Ivy, which allows it to pull together many additonal tools. Although I am still getting use to interpreting Ant code and doubt that I would be able to write Ant code on my own, I have already reaped many of the benefits from Ant. It provided an easy way to evaluate my code for possible errors, and also packaged my robot for me, for easier distribution to others. I look forward to having Ant available to me for future projects, and also learning how to adapt Ant further for use in other projects.

Monday, September 21, 2009

Robocode Battling: Battle 1

In my last entry, I wrote an analysis of the strategies used by a selection of the sample robots in Robocode, the battle robot program that I have been working with for the last three weeks. Over the last few days, I have worked to develop a robot that will generally defeat as many of these sample robots as possible, when placed in a 1-on-1 battle. This represents my first attempt to design a battle robot, after spending the last several weeks learning basic Robocode movements and studying sample strategies.

Before I began programming, I tried to think of what general strategy I should use. It seemed like it would be best to keep my robot constantly moving in some generally straight pattern, so as to avoid any bullets that are shot at me, as well as to avoid swerving back into stray bullets. Other than that, I decided to adopt one of the instructions from the basic robots that I constructed two weeks ago, to fire using power proportional to the enemy robot's distance.

I began by writing my own implementation of the sample robot Walls. Although this consistently beat all other sample robots as expected, I wasn't happy with the fact that I was simply copying the exact idea of a sample. Furthermore, my implementation of Walls had a very difficult time dealing with Corners.

I then decided to simplify my robot, by having it essentially pace back and forth along one wall, keeping the advantage of having fewer directions for enemies to target it from, as well as the advantage of being able to shoot at most enemies, since none could be directly behind my robot. However, again I had trouble dealing with Corners, since my robot generally shot straight ahead, and half of the time Corners would be to the side of me. I then gave my robot some evasion tactics, by having it move to the opposite wall when it hit another robot, and thus PacerEvader was born.

My robot's overall strategy can be summarized as follows:



PacerEvader
(Source code)
Movement: Moves back and forth along the top wall. If it hits a robot, it moves to the opposite wall and resumes moving back and forth.
Tracking: No sophisiticated tracking; it will look for enemies to target arbitrarily.
Firing: Fires when an enemy is spotted, using power proportional to the enemy's distance (more power for closer enemies).



Here are the results of 1-on-1 battles between my robot and each of the samples. As a note, points are awarded for a variety of battle elements, including successful shots, ramming into other robots, and surviving. The winner is based on overall score, and not the number of placings in survival. I have provided the score percentage, as well as the number of wins in actual battle.

Walls: score percent: 12; 3 wins, 97 losses
RamFire: score percent: 48; 66 wins, 34 losses
SpinBot: score percent: 73; 89 wins, 11 losses
Crazy: score percent: 78; 94 wins, 6 losses
Fire: score percent: 92; 99 wins, 1 loss
Corners: score percent: 85; 99 wins, 1 loss
Tracker: score percent: 55; 58 wins, 42 losses
SittingDuck: score percent: 100; 100 wins, 0 losses

So overall, my robot can win against SpinBot, Crazy, Fire, Corners, and SittingDuck. Furthermore, it approximately ties with RamFire and Tracker, leaving its only real problem opponent as Walls. I believe that PacerEvader is successful because it constantly moves, generally avoiding bullets from semi-stationary targets, and it does not waste power excessively on targets that it has little chance of hitting.

I had a lot of headaches while trying to develop my battle robot. Most of the problems occurred while I was still trying to implement a very close copy of Walls, and as I was trying to do too much with a single robot. I don't think I completely understand the order of events as they are triggered, since I was having trouble generating OnScannedRobot events when I needed them to be, despite putting in scan() commands when my robot's gun would be pointed directly at a target. This is still an unresolved problem, since I merely developed a crude, inefficient workaround before abandoning that battle strategy altogether. My main lesson learned from this was that it is impossible to program without having a firm grasp of what you are trying to do, as well as the tools that you're working with. Although the Robocode API was extremely helpful, I was thinking out of the scope of my programming abilities.

For future development, I would like to find a strategy that will reliably beat Walls without compromising results against too many of the other sample robots. If possible, I think that I should also look into other ways to earn more bonus points, since RamFire beats PacerEvader from the bonus points earned through ramming my robot, rather than surviving until the end of the battle.

Wednesday, September 16, 2009

Robocode Strategy Analysis - Preparing For Battle

“To be prepared is half the victory.”
- Miguel de Cervantes Saavedra

One of the main objectives of building Robocode robots is to program robots for competitions. Thus far, my Robocode experience has consisted of programming basic robots that often do not attempt to attack enemy robots in any way, shape or form. Now, I have embarked upon the first steps in the process of building a competitive robot.

The Robocode download includes fifteen sample robots that make use of a wide variety of strategies. I looked at some of these robots while completing my thirteen basic robots for class, but for the most part, they were robots that I could include in a field to test anything that was supposed to track and/or fire at enemies. So today, I examined eight of the sample robots, and looked at their approaches to the following elements of robot operation:
  • Movement: How does the robot move? Does it have an avoidance or following strategy?
  • Targeting: How does it find a target to fire?
  • Firing: What is its criteria for firing?
What follows are my observations on the robots that I studied.



Walls
"Moves around the outer edge with the gun facing in"
Movement: Generally ignores enemies during movement. If it collides with an enemy it moves away from the enemy slightly, before continuing its usual pattern of movement.
Targeting: Moves along outer wall in a regular pattern; fires at any enemy robot when scanned
Firing: Fires at any enemy

Overall observations: This seems to be a good way for a robot to stay alive, but it does not appear to be very efficient in killing other robots because the robot has very few opportunities to shoot at any one robot.



RamFire
"Drives at robots, trying to ram them. Fires when it hits them."
Movement: RamFire tries to ram into robots, which earns bonus points.
Targeting: It does not fire until it is hitting a robot. It does not track any enemy in particular.
Firing: It fires at any enemy, once it rams into the enemy. It uses a low enough power that the target will not die, so that RamFire can continue to ram into the enemy.

Overall observations: This seems to be a very effective way to earn bonus points in battle.



SpinBot
"Moves in a circle, firing hard when an enemy is detected"
Movement: Turns continuously in a circle; neither follows nor avoids enemies, although if it rams into another robot, it moves off to the side before resuming circling, thus giving it a slight avoidance technique.
Targeting: It continuously turns in a circle, searching for enemies.
Firing: Fires at any enemy spotted, with the maximum bullet power.

Overall Observations: This seems to be a good way to inflict a high amount of damage on enemies, but I'm not sure that it's a good idea to always use the highest possible power when firing at any enemy. It seems to have good evasion tactics against other robots, since it's more difficult for a robot to aim at SpinBot.



Crazy
"Moves around in a crazy pattern"
Movement: Does exactly as its name says; swerves left and right, reversing if it hits walls or robots. Moves away from robots it hits, so somewhat of an avoidance strategy, although it isn't proactive.
Targeting: Just looks for anything that crosses its path.
Firing: Fires indiscriminately at any enemy it sees.

Overall Observations: This robot really lives up to its name! It seemed to do reasonably well in combat, but I really couldn't follow what it was doing and a lot of what it succeeded in doing appeared to be luck, since it moves around randomly until it happens to hit something.



Fire
"Sits still. Spins gun around. Moves when hit."
Movement: Moves only when hit by a bullet.
Targeting: Spins its gun slowly, aiming at everything it detects.
Firing: Takes health into account while firing. Fires larger bullets if the target is healthy and nearby close. Otherwise, fires using power 1.

Overall observations: This is a simple robot that still attacks with some strategy.



Sitting Duck
"Sits there and provides a target until dead."
Movement: Does not move at all.
Targeting: Does not target at all.
Firing: Does not fire at all.

Overall observations: A good robot to use while testing, but it definitely does not have any strategies that I would want to make use of in combat.



Corners
"Moves to a corner, then swings the gun back and forth. If it dies, it tries a new corner in the next round."
Movement: Runs into a wall, turns left, and hits a corner. If it sees a robot, it stops and aims at it.
Targeting: Pans back and forth from the corner, targeting the first robot it sees.
Firing: Fires using more powerful bullets the closer the target is to itself.

Overall Observations: Corners seems rather vulnerable to other robots because it sits in one place for the entire round. Any robot that picked a specific target to attack would probably have a huge advantage against Corners.



Tracker
"Picks one robot, follows it to a certain distance, and attacks it until it's dead."
Movement: Scans the area, not moving until a robot is spotted. Once a target is spotted, Tracker follows it within 80 pixels or so, attempting to maintain this distance. It does not move if it loses it's target.
Targeting: Targets a single robot, and fires upon it until it's dead.
Firing: Fires with a power of 3 at the target robot no matter what.

Overall Observations: Tracker does what its name says very well. However, it doesn't seem like this is an effective single strategy for battle.



Overall, this exercise was useful because I was able to see the full range of possible strategies I could have my robots adapt. The one main idea that seemed to work was to have the robot keep moving - SittingDuck and Corners both were very unsuccessful in killing enemy robots. I think that I am beginning to formulate some ideas as to what strategies I would have a competitive robot implement, but the one thing that this exercise has shown me is that testing will be a big part of perfecting whatever plan I do decide to work on.

Monday, September 14, 2009

Robocode Edting - Conforming to Standards, and The Case of the Missing Symbols

As part 2 of the Robocode assignment for class (as discussed below), I went through all thirteen of my implementation files and edited them to match the following coding standards:
where the rules of earlier listed items superceed any following standards.

My edited code can be found here.

Coding standards are important because they promote understanding of a program, both by future users as well as the author. Programmers who carefully implement coding standards create code that works as it was designed to, because they document the purpose of each piece of a program. Furthermore, if the meaning of something is altered in the programming process, the programmer will become aware of such changes as variable, method, and class names no longer make sense. Coding standards are important because it creates a uniform work that can be read more easily by others. Even if people use slightly different coding standards, they will still be able to more easily adapt to a single style within a programming project than a programming style that jumps everywhere. Coding standards promote neat, organized code, and these characteristics will always increase the readability of a program.

For me, the editing process was relatively painless, since I had taken the time to organize and comment my code for the first submission. The two major things that I needed to do were to import the ICS SE Eclipse formatting file, which would provide a template for my code in Eclipse, including using spaces instead of hard tabs. Although this was something I had to do only once for the entire assignment, it was significant because I had no idea that it was possible to define your own formatting within Eclipse, much less how I could go about doing so.

Second, I had to edit the comments within my files. The biggest change was that I had to add in JavaDoc comments. Prior to this class, I honestly had no idea what a JavaDoc comment was, and before this specific assignment, I really didn't know how to use them. I'm actually surprised that none of my introductory Java courses at UH taught us about the JavaDoc comments; I remember my teachers emphasizing commenting, but we didn't learn anything about commenting conventions or JavaDocs. In my original submission, I had used JavaDoc comments once or twice without much thought; mostly copying the style of comments when I was working off a sample robot. A lot of the edits amounted to adding in the extra asterisk at the start of my comments and reorganizing what I had so that the first sentence was the best stand-alone description of what the robot did. It was good practice for me, though, and I think that I'll find it a lot more intuitive to write JavaDoc comments this way from the start in future assignments.

Another main change I had to make to my program's comments was to re-write them to be in third-person active voice. I don't feel like I have ever used a standard voice when writing comments, so this will give me a good base to work from in the future. One commenting standard that I have not used previously was using end-of-line comments to describe the purpose of a variable. In the past, I have worried that it would be too messy and confusing, but after being consistent about using end-of-line comments throughout the project, I can appreciate the fact that they make it much easier to determine the purpose of a variable.

Finally, I'd like to include a few observations I made while reformatting my Robocode project. First, I love Eclipse's "refactor" tool, which allows one to easily rename a project or a variable within a Java document. I had a few variable names that either no longer aptly described the variable's purpose, or were not formatted correctly, and it was extremely easy to change the names of these variables and feel confident that I had made all of the necessary changes. I did run into a problem, however, when starting up Robocode to test some changes I had made - Robocode was set to look for the robots in the newly non-existent project directory, Robocode. I had to rename my project back to the original name, open up Robocode, then rename the project to the correct one for the standards, and then edit the directory where Robocode would look for robot files. It was a complicated process, but I'm glad that I did catch it right away, because I would probably have panicked if I hadn't discovered the problem until later.

Next, I realized that the smallest things can trip you up, even when "just" editing. I decided to try to better optimize some of my implementations for the movement functions, as I noted that I wanted to in my previous blog entry. For the most part, I was able to get everything to work together without a hitch after looking at Edward Meyer's code. However, my robot that was supposed to move between all four corners would just not go in the correct direction when it was supposed to navigate between the top left and bottom right corners. I easily spent half an hour trying to figure out where I changed the code, which was simply a specific adaptation of my already-working code to move the robot to the center of the field. The final verdict? I had somehow deleted an end parenthesis to end a nested function, and had solved the problem by tacking on a parenthesis at the end of the line.

Overall, I feel that this assignment was an extremely valuable learning process. Although it required little to no actual coding, it showed me that the comments for a program are just as important as the code itself. Moreover, I now have guidelines available, so that it will be easier for me to write uniform comments on future programming projects. I think that formatting programs correctly will be much easier when the coding standards are enforced from the beginning, and this exercise will serve as a reminder of the importance of getting it right (or as close to right as possible) the first time through.



Important links referenced in this post:

Wednesday, September 9, 2009

Robocode

Over the past week, I have been working with the Robocode project, a Java-based project available on SourceForge.net that allows users to create and battle robots. I downloaded Robocode from SourceForge.net, installed it on my computer, and then used the Eclipse IDE to do all of my programming. I only used the basic Robot, although there are also the AdvancedRobot and JuniorRobot.

I encountered this project as part of my software engineering class, but I didn't immediately begin building the robots that we needed to for class. Instead, I began experimenting with Robocode by going through the wiki for the project. It had a very useful tutorial on integrating Robocode with Eclipse, as well as a walkthrough on creating a baisc bot. The first robot that I created was this sample, which essentially moved along the walls of the field, firing when an enemy was in sight. The sample provided me with a basic skeleton for the code for all of my subsequent robots.

After getting a feel for Robocode, I moved on the the actual assignment. We were given descriptions of 13 basic robots that we were to implement within a week. The robots were categorized by their overall goals: movement, tracking, and firing. The process of building these robots allowed me to get used to programming in Robocode, from finding functions in the Robocode API, to understanding all of the robot's functionalities. Another resource that I occasionally turned to was this class website. Although I wasn't able to access the sample robots, there were code snippets that helped to point me in the right direction for some of the robots for my assignment.

The movement robots introduced me to the robots' coordinate system and movement options. Some of the counter-intuitive things about Robocode is that its coordinate system has the origin in the lower left corner, and degrees are measured clockwise, from the top of the screen. The origin was counter-intuitive to my experience with Java applets, which have it located in the top left corner, and I expected the degrees measured according to the unit circle, counter-clockwise from the right side of the screen. The basic Robot class can only use one move at a time, so turning or moving ahead, but not both. Thus, my general strategy was to orient the robot in the correct direction, and then move ahead the appropriate amount. I was able to implement all of the moves relatively quickly, with room for improvement as I describe later.

The tracking robots were much more challenging for me. Despite all of the practice at having my robot moving in very rigid patterns, I found it hard to get my robot to track another moving robot. Eventually, I used the Tracker sample robot provided with the download as a basis for several of my tracking robots. I had to eliminate a lot of code that was based on firing at targets, but digging through the sample code gave me a lot of experience at seeing the Robocode functions and getting a feel for what is involved in finding and tracking a robot.

Finally, with the firing robots, I moved on to having my robot shooting at other robots. Again, I found the biggest obstacle in tracking a single opponent with my gun. I ended up adapting the code from one of my tracking robots to complete this task. Firing is easy to do - you use the function fire(), which takes a single parameter on how much power to use - the tricky part is in finding your target. You can also be smart about how much power you use, so as not to waste power on targets that are very far away.

Overall, it seems like coding robots to track well is the biggest challenge we were assigned. Given more time, I would have liked to play around with my tracking code further, to be able to understand the reason for picking the intervals at which to move the robot ahead the full distance, or nearly full distance. I did end up changing the numbers for my purposes, but I don't know what would have been optimal.

I was able to successfully implement all 13 robots. However, I would be interested in optimizing some of my movement robots. Several of them move in a stair-case motion, going up, then across, or vice-versa, instead of moving in a diagonal line. I implemented the robots this way after running into some difficulty trying to get them to complete moves with a single straight line and opting to code in a way that I knew worked and that would save me time coding.

My implementation of all 13 basic robots for class are contained in this zip file.


Important links referenced in this post:

Sunday, August 30, 2009

FizzBuzz

On the first day of ICS 413, Dr. Johnson instructed us to implement the FizzBuzz program in Java. My first thought upon hearing the assignment was "I've forgotten a lot of Java knowledge!" Over the summer I had been doing programming in Maple, a technical computing software, during a mathematics research program; moreover, the last time I did any programming in Java was almost a year ago, last fall. So although I could immediately visualize the algorithm that I wanted to implement, it took a little bit of thinking to remember Java's syntax.

In the time given in class to write the program by hand (around five minutes, I think), I was able to complete the program with what I believe would have amounted to a few syntactical errors. Later, when I used the Eclipse IDE to write the program, I had no problems and was able to implement the program within a few minutes.



Program description:
Write a program that prints the numbers from 1 to 100. But for multiples of three print "Fizz" instead of the number and for the multiples of five print "Buzz". For numbers which are multiples of both three and five print "FizzBuzz".



My program:

/*
*  This program prints out the number from 1 to 100, inclusive, with one
*  number on each line. However, if the number is divisible by three, it
*  instead prints the word "Fizz", if the number is divisible by five, it
*  instead prints the word "Buzz", and if the number is divisible by both
*  three and five, it prints the word "FizzBuzz".
*/
public class FizzBuzz {
  
public static void main(String[] args){
      
      
// Loop through the number from 1 to 100
      
for(int i=1; i<=100;i++){
          
if(i%15==0){
              
/*
                *  If the number is divisible by both 3 and 5 (i.e.
                *  divisible by 15), print out "FizzBuzz".
                */
              
System.out.println("FizzBuzz");
          
}
          
else if(i%3==0){
              
// If the number is divisible by 3, print out "Fizz".
              
System.out.println("Fizz");
          
}
          
else if(i%5==0){
              
// If the number is divisible by 5, print out "Buzz".
              
System.out.println("Buzz");
          
}
          
else{
              
/*
                *  If the number is not divisible by 3 or 5 (or both),
                *  then print out the number.
                */
              
System.out.println(i);
          
}
       }
   }
}




This experience has shown me that even the simplest of programs can be good exercises to get used to programming in a language that one has learned in the past but may have not used recently. Also, the experience has shown me not to dismiss programming assignments as trivial or to underestimate an assignment.

Evaluation of PDF Split & Merge

Recently, I downloaded, installed, and made some trial runs of PDF Split and Merge (PDFsam). The program provides a way to split the pages of PDF documents into smaller files, and a way to merge selected pages from multiple PDFs.

I downloaded PDF Split and Merge Basic Version 2.0.0 for Windows from SourceForge.net. On the website, the program describes itself as "an easy to use tool to merge and split pdf documents". I first tested version 1.2.0, which was available when I initially downloaded the program on Wednesday, August 26, but after writing part of this review I checked the website again and was pleasantly surprised to find a newer version. This evaluation will focus on the most recent version, although I will make some comments on changes within the program.

To evaluate the program, I will be using Philip Johnson's Three Prime Directives for Open Source Software Engineering. In summary, the three prime directives are:
  1. The system successfully accomplishes a useful task.
  2. An external user can successfully install and use the system.
  3. An external developer can successfully understand and enhance the system.
First of all, this program definitely accomplishes a useful task. I found PDFsam while browsing SourceForge.net, and the program caught my eye because it sounded like something I would find extremely useful. In the past, I have had to both send and receive long PDF documents where only a few pages were necessary. Recently, I received a 130 page document of which only one page was truly relevant, and I needed only one other page for minor references. In instances like this, I would have appreciated a program that would allow me to pick out selected pages from the document, which would make browsing for information much easier.

Second, it is relatively easy to successfully install and use the program. PDFsam used an installation wizard and fully explained each step and installed exactly as expected. Upon opening the program initially (in version 1.2), I found the layout very sparse and somewhat void of directions. However, a tutorial file is included in the installed files, and after reading the tutorial, I found it easy to use the program. My one other problem arose when I couldn't figure out how to run the program on selected files, because the "Run" button is located at the bottom of the window and I needed to scroll down to see it.

Finally, I believe that as an external developer, I would find this program to be very difficult to enhance. After looking through the documentation provided during installation, on SourceForge.net and at PDFsam.com, I was unable to find any resources for developers. Without this documentation, I feel that it would be next to impossible to interpret code if it was necessary to adapt the program for my own purposes.

Overall, PDFsam is an extremely useful program and is easy to use after a slight learning curve. I will definitely keep this program installed on my computer and continue to use it.


Links referenced this post: