Sunday, December 9, 2007

Prime Directives Redux

Today's assignment is PrimeDirectivesRedux, where we reexamine some of our past assignments in terms of the Three Prime Directives.


The Three Prime Directives

  1. The system 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.

One thing that's not included in the prime directives, but which several of the tools help support, is the ability of an external developer to join the project and become an internal developer.

Interactive Development Environments (Eclipse, VisualStudio, etc.)

An IDE is mostly focused on helping you create any system at all. Since the system needs to exist before it can satisfy any of the directives, it helps in that sense.

More directly, it can help satisfy Prime Directive Three by encouraging consistent structure and idioms. IDEs automate a lot of common tasks, and the results are usually very consistent, making the code easier for an outside developer to understand and extend.

Coding Standards and Coding Standards Compliance Tools (Checkstyle, etc.)

Coding standards and compliance tools also provide consistency, though of a different type. Again, consistent style helps external developers understand the code.

There's no direct effect on the first two Prime Directives, because the coding standards aren't going to directly make the system easy to install or change what it does.

Build Systems (Ant, Make, etc.)

A build system can output a single file for external users to download and install from, so that's quite helpful for Prime Directive Two.

By automating some important development tasks (building, of course, but also testing) a build system makes the development environment easier to learn and use, which helps with Prime Directive Three.

A build system also makes it easier to run tests on the system. That's helpful for Prime Directive One because it helps check that the task is being successfully accomplished.

Automated Quality Assurance Tools (PMD and FindBugs, etc.)

These tools help ensure that the system successfully accomplishes whatever task it is designed to accomplish, which can help with Prime Directive One.

They also help with Prime Directive Three by making it easier for external developers to successfully integrate their changes into the system. A system that passes quality assurance tests is also usually easier to understand.

There's no direct effect on installation, but preventing bugs with quality assurance can make the system easier to use.

Black and White Box Testing

Testing supports Prime Directive One by helping ensure that the system successfully accomplishes whatever task it's designed to accomplish.

It also helps with Prime Directive Three by giving external developers a "safety net" when making changes. They can see right away whether their change broke something.

Again, there's an effect on Prime Directive Two, in the sense that a system with fewer bugs tends to be easier to use.

Automated Testing Tools (JUnit, HttpUnit, etc.)

Automated testing tools make black and white box testing easier, so all the same effects apply. The tools are especially helpful for Prime Directive Three because they simplify an development task (running the tests) that could otherwise be much harder to learn.

Configuration Management (CVS, SVN, etc.)

Configuration management is focused on how the internal developers store and track the code, so here's no direct effect on the Prime Directives, except maybe Prime Directive Three if you make your commit logs available to external developers.

There is a strong, indirect effect on all three Prime Directives because configuration management makes it much easier for internal developers to work together and get things done.

Issue Driven Project Management

Like configuration management, issue driven project management is mostly about how internal developers run the project. If the issues are made public, they can sometimes be helpful to external developers and users, but mainly it helps the internal developers work more effectively, which might mean they do a better job of satisfying all three Prime Directives.

Use Cases

Use cases help define the tasks that the system is supposed to accomplish, which helps with Prime Directive One.

They can also make the system easier to use by getting the developers to think about what the experience of using the system is supposed to be like. Things like the number of mouse clicks needed for a common task can show up in the use cases.

It can also be helpful for an external developer to read the use cases. Understanding what a system is supposed to do is an important part of understanding it in general.

Software Review

Software review is particularly important because the Three Prime Directives are defined in terms of other people. In a software review, some external person can check that the system is useful, installable, usable, understandable, and enhanceable.

When they find places that it isn't, the internal developers can work on fixing the system to better satisfy the Prime Directives.

Agile Methods (XP, Scrum, etc.)

Agile methods emphasize communication with users, which helps with Prime Directives One and Two. Users can tell the internal developers what's needed to satisfy the Prime Directives, and the developers can make adjustments.

The effect on Prime Directive Three probably depends a lot on which particular method you are using and the particular developer. The agile method itself won't include external developers, but it can lead to things that are helpful to them, like good unit tests or simple implementations.

Open Source Licenses (GPL, CPL, etc.)

An open license has no real direct effect on Prime Directives One and Two because it doesn't directly affect the behavior of the program.

It will make a big difference for Prime Directive Three. If an external developer is not allowed to read the source code and modify it, then Prime Directive Three is clearly not being met.

Online Hosting Services (Google Project Hosting, SourceForge, etc.)

An online hosting service helps with Prime Directives Two and Three by giving external users and developers a place to get the system and information about it.

It also helps in a general way by making it easier for internal developers to get things done, which hopefully brings them closer to satisfying all three Prime Directives.

Friday, November 16, 2007

MyISERN 1.3 review

Today's assignment is MyIsern-1.3-review. I'm reviewing the team orange code, which is here.


Installation

The package I downloaded was myisern-orange-1.3-1.0.1114.zip. There was no installation guide, but it installed fine using the installation process we're all using. I had to look up a few things that would have been in the installation guide, but the installation worked.

JUnit, Checkstyle, PMD, and FindBugs tasks all ran cleanly.

Code Format and Conventions

Nothing really leapt out at me as far as coding conventions, except that some of the comments are out of date.

I would recommend that they split things up into multiple ActionBeans rather than just expanding the ActionBean from StackStripes to do everything, but that's not really a coding convention.

Test Cases

Emma Coverage summary

class:14%(3/22)
method:1%(3/215)
block:1%(16/3032)
line:1%(7/773)

White Box & Black Box

There are two tests: a test that the welcome page can be retrieved and a test that is turned off and prints out the number of records loaded from XML.

From both a white box and a black box perspective, this is rather limited testing.

Breaking

  • Trying to list or edit anything causes a null pointer exception
  • Trying to add a record causes a file not found exception. I think this one is caused by looking for the files in the wrong place. The directory is supposed to named .myisern, not myisern. (It's supposed to have a period at the beginning.)

User Interface

I was able to use the interface.

It uses very little screen space and works fine with only a quarter of my (small) screen.

The one thing I would improve is the labeling of the links on the main page. The links should probably contain the name of what they do ("edit" or "add"), so you don't have to look up at the table headers to figure it out. It seems like a small thing, but it threw me off at first.

Summary and Lessons Learned

This version of MyISERN doesn't do any of the things it's supposed to, but it's a pleasant improvement over the last piece of software I reviewed.

It compiles, installs, and runs. It doesn't run correctly, but that didn't get in the way of writing a review.

It will, however, need to run correctly by Monday.

Wednesday, November 14, 2007

MyIsern 1-3

Today's assignment is MyISERN-1.3.


This assignment doesn't actually say that we're supposed to do a log entry, but I thought I'd give the reviewers an easy place to download it from.

Unfortunately, not all tasks were fully completed.

The New Group

My new partner is Randy Cox.

I was the member who had been working on the same codebase from before, and I had been working on the model (which was the part we were keeping as we switched to a Stripes webapp) so I again worked on the model in this increment and Randy handled the view and controller.

The Work

The model changes were more extensive than I had originally hoped, mostly because of the concurrency issues. In the single user version, the model was just returning a reference to an object that it continued to hold onto and give out to. Even if the methods returning the references were synchronized, the lock would be released by the time the caller started actually using the object, which could then change out from under it.

I suppose I made that part of it harder than it should have been by trying to have a solution that I liked rather than one that just did the job. I ended up with something that worked and only sort of pleased me.

I also did the installation guide and the"sanity check" report, which technically means that I did a little of the view and controller, but not really. That part was just a thin wrapper around a report generated in the model. Randy did all the username/password, ActionBeans, etc.

The Result

There are still two unfinished parts of the program:

  1. Test coverage is poor
  2. There's some kind of problem with displaying list values

The poor test coverage is largely from try-catch blocks that never catch and a large method we're not calling because we're not sure if we want to keep it or not.

The list problem has something to do with list data (years, affiliatedResearchers, and other things where you can have more than one) not showing up on the page.

Randy mentioned it while I was finishing up the "sanity check" report, and I ran a few tests. The data was getting from the model into the ActionBean but not from there to the page. At the time, the problem looked (to me) like the JSP code wasn't making any calls to retrieve the data. I'm not sure where he went from there, but I think it was left unresolved. It's definitely something we should talk about in person and try to sort out by Monday.

Monday, November 5, 2007

Web App Questions

  1. Explain in your own words the meaning of the web "request-response cycle".

    The client sends a request to the server, the server processes the request, the server sends a response, the client figures out what it wants next and sends another request, and the cycle repeats.

  2. Explain how servlets facilitate processing of the request-response cycle.

    Servlets to the server-side processing of the cycle. There's a framework that handles receiving the request and sending the response, so you can complete the server side by creating servlets.

  3. How do you login to the Tomcat Manager?

    Go to the top level page on the server and click the link.

  4. What is the Tomcat Manager used for in the StackStripes application?

    It's not really used inside the application, but the build system uses it to deploy and undeploy the application (and check that it has access to deploy and undeploy).

  5. What is the directory and file layout of an installed web application like StackStripes? (This is NOT the same as the directory and file layout of the StackStripes distribution!)

    At the top level, there are JSP pages and the WEB-INF directory. WEB-INF contains web.xml and the directories classes and lib.

  6. How do you build a war directory structure in Ant? Where is this accomplished in the StackStripes application?

    The directory structure is built by creating a WEB-INF sub-directory and putting web.xml, classes, and lib. In StackStripes, there's a web directory that already contains the complete structure and the build system copies it to create the directory used to make the war file.

  7. How do you install a war directory in a running Tomcat server? What information does the Ant task need to accomplish this?

    GET http://server:port/manager/deploy?path=servpath&war=fullpath where servpath is the path of the installed application within the server (e.g. /stackstripes) and fullpath is the full path of the war directory to install.

  8. What is the "Model2" architecture? What are its advantages?

    The design is split into a model, view, and controller. The view is what the user directly interacts with, the model stores the data, and the controller responds to what what the user does to the view by doing things to the model and view.

    The advantages are that it's fairly easy to understand and it separates three types of things that are different, allowing you to do things with just one of them at a time. For example, you can create the view using JSTL, and the controller by writing Java.

  9. What are JSP pages? How are they related to servlets?

    JSP pages are web page servlets (or parts of servlets) written in a way that directly includes the static parts of the page.

  10. Why is there a delay when retrieving a JSP page for the first time? Where is the Java code for that page stored?

    It has to be converted to Java and compiled. The Java code is stored under a long, complicated path inside the directory where Tomcat is installed.

  11. What are JSTL tags? Why are they useful? What is an example JSTL tag from the StackStripes system?

    JSTL is an extension to JSP that adds a lot of tags to take the place of inline Java, making it more of a templating system. For example, the forEach tag is used to iterate through the stack.

  12. What are Stripes tags? Why are they useful? What is an example Stripes tag from the StackStripes system?

    Additional tags defined by Stripes. They're useful because they hook in to Stripes. For example the stripes form tag sets up a form that is also connected to an "action bean" by Stripes.

  13. What is HttpUnit? How is it different from JUnit? Why is it useful? What is an example use of HttpUnit from the StackStripes system?

    HttpUnit is a library for doing HTTP requests and responses. JUnit is a unit testing framework. HttpUnit is useful because it lets you do HTTP requests and responses from inside the JUnit tests, so that that the tests pass or fail based on the HTTP results. For example, some of our JUnit tests use HttpUnit to retrieve pages and check the contents of the table which displays the stack.

  14. What needed to be changed in order to implement the Double It button? What didn't need to be changed? What did you learn about the MVC design pattern from this exercise?

    Added doubleIt to the model, doubleIt to the controller (action bean), and added DoubleItForm to the view (JSP). If your framework isn't very smart, you can find yourself doing everything three times.

  15. What are the equivalence classes that need to be tested for the Double It button?

    Empty stack and non-empty stack. You might also divide non-empty stack into one element and many elements.

  16. Provide two screen images of your new StackStripes application with the Double It button, one showing the page before and one showing the page after hitting the "Double It" button.

  17. What is the singleton design pattern? What is an example of its use in StackStripes? Why is it needed?

    Only one instance of a class can ever be created. The StackStripes model is a singleton because we want all users to share one stack.

  18. Some of the StackStripes tests exercise code on the "server side", while others exercise code on the "client" side. Which test classes exercise code on the "server", and which exercise code on the "client"? How does Emma deal with this to create appropriate coverage data?

    TestStackActionBean tests code while it is deployed, and TestStackModel tests code while it is not deployed. Emma records the results in two files and then combines them.

  19. Running 'ant -f junit.build.xml' results in the following target invocations: tomcat.check, tomcat.undeploy, compile, war, tomcat.deploy, junit.tool, junit.report, junit. Explain what each of these targets do.

    • tomcat.check checks that the server is up and we can log in
    • tomcat.undeploy undeploys the application
    • compile runs javac
    • war creates a war file
    • tomcat.deploy deploys the application to the server
    • junit.tool runs the JUnit tests
    • junit.report generates a report on the JUnit tests
    • junit depends on junit.tool and junit.report (rather pointless if you ask me -- junit.report could, and probably should, depend on junit.tool and be the default)

Sunday, November 4, 2007

Stack Stripes Extension

Today's assignment is StackStripesExtension. My extended stack is here.


All tasks completed.

Difficulties

Nothing was particularly difficult. I ran into the problem that John Hauge brought up, but I had already seen Shaoxuan Zhang's reply, so I just started tomcat from the project directory.

I also had to add $CATALINA_HOME/bin to my PATH so that emma.build.xml could find it.

Coverage

Emma Coverage summary
class:   100% (2/2)
method:  100% (18/18)
block:   97%  (142/146)
line:    94%  (39.6/42)

When I did Task 4, adding an HTTPUnit test, I noticed that the isEmpty model method wasn't being called anywhere in the controller. That pretty much ruled out 100% method coverage via HTTPUnit, so I settled for ninety-something.

In Task 5, I added tests of isEmpty to the non-HTTPUnit tests at the same time that I added tests for my new doubleIt method, so method coverage did end up at 100%.

Lessons Learned

Being told to shoot for 100% method coverage kills any desire to do black box testing. The tests we did for MyISERN-1.2 were much better, even though Emma reported less coverage.

Monday, October 22, 2007

MyIsern-1.2

Today's assignment is MyISERN-1.2.


All tasks completed.

Group Process

My partner Kevin English really got into the text interface on this assignment. We had already divided it up on a previous assignment so that he was doing the interface, but on this one he really seemed to have a vision of how it should work. He volunteered to do all the data inputting, so he was writing code for himself to use.

I tried it out a little, and it is a nice interface. It's actually menu-driven rather than command-driven and pretty intuitive1.

As far as working together, we mostly did what we've done on past assignments: meet as often as we can, kick some ideas around, and then decide what we'll do until the next meeting. Since I'm writing the model, a lot of the group interaction has been about what methods my partner needed me to implement.

Difficulties

The main difficulty we had was with JAXB and Java. Every time we've used it, we've thought about wrapping JAXB somehow, but we never did. The problem is that we couldn't find a way of wrapping it that would solve the problems we were having without being more work than the problems themselves.

For me, working on the model, the problem manifests as doing things three times. For Kevin, it was probably different.

When we first started using JAXB, I thought maybe we could just wrap or convert the three JAXB objects into things that formed an inheritance tree. But there was really only one method they had in common. The problem was that they had many repeated methods which were analogous but not identical in type or number.

Kevin has his own take on the problem, but I look at it this way:

Java doesn't let you merge, or even blur the line between, object structure and metadata. Objects can't easily inspect each other's structure and interact based on what they discover. It's also very rigid about types. JAXB, on the other hand, converts XML entities with children to classes with fields. The sum is that you lose the ability to treat the structure of the data as data that can direct the code. Instead, it's an invisible (to the objects) structure that you must hard-code the objects to synchronize with.

To really get around that, as far as I can see, the wrapper would have to be a sort of reverse-JAXB that turns the JAXB objects back into some type of self-describing data structure like a DOM tree or nested maps of strings.

That never seemed worth the effort, so we would always sort of daydream about having a solution and then keep going without it2.

I'm interested to see what other groups have to say about JAXB. I keep going back and forth between thinking there must be wonderful way around it that I just haven't figured out yet and thinking that Java and JAXB are just hopeless.

Another minor thing is that our code coverage suddenly dropped right near the end. From the reports, it looks like everything has pretty good coverage except for some enums and our old command-line interface, which is coming in at under 60%. I knew that my partner was still using parts of the command-line interface to work with the new interface, so I figured he had merged or moved the test code in some way that caused it to only test the things we're actually still using.

In any case, the sudden drop didn't seem to be caused by a whole bunch of new, untested code. I also didn't notice it till my parter was asleep, so I didn't hold up the release for it.

Next Time

Next time, we might want to do a little more of the "skeleton" of the project earlier: things like issues, unit test, and wiki pages. We sort of lost track of where we were and what was left to do, and I think that would've helped.


  1. It has a little bit of old code that I wrote in the first iteration for displaying tables. Right at the last minute, that old code started choking on nulls.

  2. We didn't realize it until the very tail end of this assignment, but there's also a problem with JAXB and null. JAXB uses null in a lot of places where an empty collection would make more sense. If I'd known how pervasive that was, I might have gone ahead and written a wrapper even if that was the only thing it fixed.

Use Case Specification

Today's assignment is UseCaseSpecification. Our use cases are here.


Our team drew up a list of the use cases we wanted, then divided them up to work on them. I expected that would lead to two different styles of use case at the end, but I was surprised at how different they turned out to be. My partner, Kevin English, took a much more formal approach. For example, his alternates always go back to the beginning and start from scratch, while mine often fork off in the middle of the typical case. Also, my mock-ups look like napkin doodles.

We actually cut out a lot of use cases because there were so many. Finding, adding, and editing each of the three types of things (collaboration, organization, and researcher) would already be nine and our target was six to twelve. We ended up not having separate use cases for finding things, and just including that as a step in editing. We also combined all the analysis into one use case.

We mostly followed the tips on how to write good use cases, but I think mine might have been a little on the terse side. It's very easy to come up with use cases, but it's hard to remember all the rules and it's easy to do too many.

Wednesday, October 17, 2007

MyISERN Review 1.1

Today's assignment is MyIsernReview-1.1. I'm reviewing the code of Marcius Bagwan (team blue). The team blue code is here.


Installation

The project downloaded and unpacked fine, but when I tried to build the jar file, I got an error message:

BUILD FAILED
/tmp/myisern-xml-1.1.1015/build.xml:45: This package requires SWT_HOME
to be defined and /tmp/myisern-xml-1.1.1015/${env.SWT_HOME}/swt.jar
available

I didn't know what SWT stood for. The acronym wasn't expanded in any of the build.xml comments, and there was nothing in the developer guide about it. It turned out to be a graphical interface toolkit called Standard Widget Toolkit. I downloaded it and set SWT_HOME, and the jar built.

But then it didn't run:

$ java -jar myisern-1-blue.jar -describe -all Researchers
Exception in thread "main" java.lang.NoSuchMethodError: main

I fixed build.xml to look for "main" in a class that actually had it, but it still wouldn't run:

$ java -jar myisern-1-blue.jar -describe -all Researchers
Exception in thread "main" java.lang.NoClassDefFoundError:
org/eclipse/swt/graphics/Drawable

And it didn't verify either:

[checkstyle]
/tmp/myisern-xml-1.1.1015/src/edu/hawaii/myisern/example/TestMyIsernXmlLoader.java:7:1:
Redundant import from the same package -
edu.hawaii.myisern.example.MyIsernXmlLoader.

BUILD FAILED
/tmp/myisern-xml-1.1.1015/checkstyle.build.xml:30: Got 1 errors and 0
warnings.

Coding Conventions

After all that, I didn't look very hard for coding violations. One thing I noticed is that a lot of code is commented out using // instead of /* */ (EJS-36).

Test Cases

Black Box

Nearly all the tests are black box tests of the checkArguments method, which accepts the command-line arguments and prints out the results. It also returns a boolean flag that is true if the arguments are valid and false if they are not. With a few exceptions, the tests are all of this flag.

Some tests that could be added:

  • query for an object that isn't there (and verify that the program handles not finding it, not just that the arguments were well-formed)
  • invalid xml (blank name, out-of-range year, dangling reference)
  • check correctness of output (before printing)

White Box

There were only two tests that seemed to be white box: One reaches into the XML loader and checks that the Collaborations XML tag is present, and the other tests an isLinkValid method (for URLs) that doesn't seem to be called outside the object itself.

The code is hard to follow, and I don't think I understand it well enough to recommend many white box tests. I can recommend:

  • test whatever it's doing with SWT
  • test the main method

Breaking

It's already broken. Running it, with any arguments, is a test that causes it to crash.

Summary

Right after I posted this and sent the email, I realized I forgot this section. It's not actually due yet, so I'll add it now.

In summary, the program doesn't run.

The lesson I learned is how hard it is to evaluate a program that doesn't work at all. (By "evaluate," I mean that it's hard to examine. It's very easy to form an opinion.)

Monday, October 15, 2007

MyISERN-1.1

Today's assignment is MyISERN-1.1.


All assigned tasks completed.

Difficulties

The main difficulty was figuring out how to design the program and organize ourselves. My parter Kevin English has a lot of experience with MVC using Ruby on Rails, so we decided to use an MVC design. Kevin worked on the controller and the view, and I worked on the model.

We were also a little unsure about how the model should look. We started writing out method calls showing how it would be used, and then we though maybe we should try test-driven design. So, for the model at least, I was using TDD.

I came up with a technique of commenting out the @Test annotation (as //TODO @Test) and using Eclipse to generate stub implementations so that I could check in the unit tests before the "real" code without breaking verify. It worked fairly well -- writing the code seemed to go a lot faster with the tests in place1.

The biggest problem as far as organizing the group was the model interface. I think we spent most of two meetings talking about what the method signatures would be. Finally, it was all settled. Then right after the last meeting before release, I got an email from my partner telling me I had done it wrong.

Next Time

Next time, I'd like to nail down all the interfaces between code that will be written by different people before anything else is done. It might help to print out the Javadoc HTML and bring it to the meetings.

We seemed to be meeting more as time went on. I guess it helps more than we expected.

I wouldn't mind using TDD again, but I really think it's time to add a web interface and a database. It gets harder and harder to add those as the project gets on. I don't care how agile you think you are, this is a huge risk. It's like we're deliberately simulating the type of insane requirements flux that kills projects2.

I wrote our current data model, and I know that it will have to be thrown away when we go from JAXB objects to a database. Obviously, the same is true for my partner's command-line and text table code when we go to the web.

Why didn't we write an abstraction layer so that we can easily switch? Doing that so it actually works is a lot harder than it sounds. I doubt anyone has had enough time to even come close.

(I just saw Kevin's entry. I agree, it's also time to ditch Java.)

Wednesday, October 10, 2007

MyIsernReview

Today's assignment is MyIsernReview. I'm reviewing the code of Andrew Wong (team silver). The team silver code is here.


Installation

Downloading, unpacking, verifying, and building the distribution all went fine. When I ran the jarfile, it printed out a nice help message, telling me to use -tabs or -console to choose the type of output. Both ways worked as advertised.

Code Format and Conventions

Per our instructions, I spent only a few minutes looking for violations, and none leapt out at me.

Test Cases

Black Box

The unit tests included these black box tests:

  • Test that the number of records printed is the same as the number of records given.
  • Check that no records are printed when no records exist.
  • Test that the program runs.

The box couldn't be completely black because a lot of the methods being tested print their results. The tests mostly went by status flags in the return values. (For example, the method that prints out records returns the number of records printed and the test checks that return value.)

The problem of testing printed output doesn't have any perfect solution (that I know of) but it might be better to have methods that return the complete output and test that. It would also be good to test the contents of the output and the number of columns.

White Box

Emma reports 100% coverage.

The white box test were geared toward testing the column formatting in console mode. There's a method called getColumnSize that takes an array of strings representing a column and figures out what the width of the column should be. The method actually takes the length of the longest string in the column and uses the next multiple of ten after that, so there are several white box tests using string lengths chosen to test the rounding logic.

There are also tests that the program runs in the right "mode" based on the command-line arguments.

The table structure is basically hard-coded, so a lot of the code is a bunch of method calls that have to be in the right order to put things in the right column. It would be good to test that things are actually going in the right columns.

Breaking

With the XML input given in the specs, there are really only two cases for the program to cover, and it basically goes straight through and does them. The only way I can see to break the program is to drop the assumption in the spec and give it other data, which I think doesn't count.

There is one thing I noticed. It's not technically "incorrect output" but some of the columns in console mode are much wider than they need to be. The data is trimmed of whitespace before it's put in the table, but the getColumnSize method is passed an array of the untrimmed data. That's pretty easy to fix.

Lessons Learned

The main thing I learned is that System.out has a format method that's good for printing columns.

Testing a program like this is a little odd. The input is fixed, so you could just have a test that does a giant string comparison on a string that's printed out as the entire output. In fact, you could have a program that just prints out a hard-coded string.

It's kind of silly, but now that I think of it, I wish I had done that. It would have been a lot easier.

Monday, October 8, 2007

15.MyISERN-1.0

Today's assignment is MyISERN-1.0.


Lessons Learned

Group Work

My partner on this project was Kevin English. He had to be on the mainland from Friday until Monday, so we probably did things a little differently than other groups.

Kevin set up the project on Google and did as much of the code as he could before he left. While he was gone, he could get email and a web browser, but didn't have his development environment. So from that point on, he worked on the wiki and I worked on the code.

We ended up not really using the "discuss" Google group and just sending each other email directly. With more people that might have been bad, but with just two it was not a problem.

The main lesson for me was that if you can divide up the work very clearly, by area or time or both, it helps lessen the effect of physical separation.

JAXB and XML

I didn't really learn anything about JAXB or XML, except some basic background on what JAXB is for. We only used it a little, and the method calls were already in place by the time I started working on it.

The Code

When I started, the first thing I was going to do was add unit tests for the code that Kevin had written. I immediately ran into that same problem we've had before with unit testing code that prints out its results. That really seems like a flaw in Java because it gives you an easy, obvious way to write your program and then makes that way impossible to test.

I'm still not completely satisfied with the output. It prints out a table, but the "description" fields are so long that they often wrap around and mess up the display of the table on the screen. It looks okay in the Eclipse console, which doesn't wrap, but when you run it from the command line, it looks messy.

In the end, I figured it was better to have the output literally be a table than a non-table that looks nice when you wrap it.

Tuesday, October 2, 2007

14 CM Practice

Today's assignment is CM Practice, where we practice setting up a project on Google according to the class conventions.


All three tasks accomplished successfully.

Subversion Client

I already had the command-line client installed, so I decided to use that. One benefit is that I can just paste my command lines into this entry.

Improving Stack-Johnson

Every time I use svn with a new server, there are a few rough spots. No two servers are set up in quite the same way, and I always seem to want to use some feature of svn that I haven't needed in a while, like reading only the log message of the change I just committed. It took a little reading of the docs, but went fairly well:

$ svn --username brian.jaress checkout \
https://stack-johnson.googlecode.com/svn/trunk stack-johnson
$ cd stack-johnson
$ ant -f verify.build.xml

(At this point, I made my change.)

$ svn diff
Index: src/edu/hawaii/stack/EmptyStackException.java
===================================================================
--- src/edu/hawaii/stack/EmptyStackException.java       (revision 34)
+++ src/edu/hawaii/stack/EmptyStackException.java       (working copy)
@@ -1,7 +1,8 @@
package edu.hawaii.stack;

/**
- * EmptyStackException is thrown when an attempt is made to pop an empty stack.
+ * EmptyStackException is thrown when an attempt is made to pop an empty
+ * stack or check its top element.
 *
 * @author Philip M. Johnson
 */

$ ant -f verify.build.xml
$ svn commit

(Filled in the log message.)

$ svn update
$ svn log -r HEAD
------------------------------------------------------------------------
r35 | brian.jaress | 2007-10-02 09:19:18 -1000 (Tue, 02 Oct 2007) | 4 lines

Expanded EmptyStackException class comment to mention that it's thrown
when checking the top of an empty stack.

------------------------------------------------------------------------

Creating a New Project

This task was mostly about setting up a Google project in exactly the class-approved way. The biggest difficulty was that the instructions were in the form of a slide show full of screenshots that I couldn't really make out. I spent a lot of time squinting at pictures that were either tiny or blurry, depending on how much I zoomed in.

Once the Google side was all set up, I just had to bring the files in:

$ svn --username brian.jaress checkout \
https://webspider-jaress.googlecode.com/svn/trunk
$ cp -R webspider-jaress/* trunk
$ cd trunk
$ svn add *
$ ant -f verify.build.xml
$ svn commit

Then I checked my email and confirmed that I had gotten a message containing the change.

Lessons Learned

I learned a few quirks of Google Code and Google Groups and puzzled out our class conventions for how they should be used. I also discovered a few quirks of Subversion that I hadn't known about, like having to do an update before you can see your own commit in the log.

Saturday, September 29, 2007

WebSpider Review

Today's assignment is WebSpider Review. I'm reviewing Ben Karsin's spider.


Installation

The package installed fine, including all the ant files. Everything verified and ant jar worked.

The one thing that gave me a little trouble was the logging. Running the program with -logging at the end of the command line didn't log anything. I was pretty confused by that until I checked the source code. All the logging code was just commented out.

Aside from that minor snag, all was well.

Code Format Fixes

All in WebSpider.java:

LineRuleRule Description
13ICS-SE-Java-4Do not include // comments at the top of the file.
40EJS-27Pluralize the names of collection references.
152EJS-36Use standard comments to hide code without removing it.

Test Cases

Black Box

The testing wasn't really being done from a black box perspective. I think there was just a decision to go with white box.

Because of that, there isn't much partitioning into equivalence classes. The JUnit tests cover a typical case (starting at http://www.hackystat.org) and the case of a bad URL for the starting page (http://). They also cover both of the command line arguments.

Some equivalence classes that could be added:

  • Pages that link to themselves.
  • Cycles of more than one page.
  • "Diamond" linking (A links to B and C, B and C both link to D).
  • Pages with links to missing pages.
  • Pages with bad URLs in their links.
  • Pages with no links.
  • Running out of pages before the maximum.

These would be tested mostly for the result rather than whether or not they throw an exception. The hackystat.org test probably already has several of these, but it's only being tested for exceptions.

White Box

Test coverage is much better from a white box perspective.

Emma reports code coverage of:

Emma Coverage summary
class:   100% (2/2)
method:  100% (7/7)
block:   95%  (346/364)
line:    94%  (68/72)

A couple of white box tests that could be added:

  • Relative links.
  • Duplicate links on the same page.

Some of the things listed under black box could also be seen as white box tests because there's specific code to handle them.

Breaking

Page with no links:

$ java -jar *jar -mostpopular 'http://www2.hawaii.edu/~jaress' 10
Exception in thread "main" java.lang.NullPointerException
       at edu.hawaii.webspider.WebSpider.main(WebSpider.java:133)

Lessons Learned

My spider actually has a very similar flaw:

$ java -jar *jar -mostpopular 'http://www2.hawaii.edu/~jaress' 10
Most Popular: http://www2.hawaii.edu/~jaress/ with null

(It should say "0" instead of "null".)

Probably the best way to fix that would be initialize the count for the start page to zero.

Seeing Ben's approach also helped me decide what I should have done differently. There were parts of my spider that I wasn't happy with, and I was thinking about how I should have done it. After seeing Ben's code I decided that the root problem was over-generalizing.

I had created a helper class that was designed as if I had no clue what it was actually going to be used for. For example, it would return objects defined in HttpUnit -- with all their error-prone methods -- in case the calling code wanted to do something wacky with it like analyze the text. It also forced the calling code to decide when it had seen enough pages, in case the decision needed to be based on some complicated logic.

That was a Bad Idea, and my helper should have:

  • Pulled the link data out of the HttpUnit object, put it into a simpler object, and returned that.
  • Kept track of the maximum number of pages.

Monday, September 24, 2007

WebSpider

Today's assignment is WebSpider. My spider is here.


All three tasks accomplished.

HttpUnit

I used HttpUnit to create fake servers for testing my spider, so I learned about the server parts of it as well as the client parts. It's a actually nicer on the server end, and I wouldn't mind using it for that again. (But it's terrible on the client side.)

Logging

I didn't spend very much time on logging. I just grabbed something from Logger.getLogger and used setUseParentHandlers to turn it on and off. That seems a bit crude, but it works.

Kevin English posted some nice code to suppress all those HttpUnit stack traces. It's not really a part of logging, but it cleared away the screen so I could see my log.

Java

I had a very interesting time with Java on this project. HttpUnit (on the client side) has a bad habit of declaring checked exceptions that it never throws, then throwing many different unchecked exceptions that crash the program.

At the same time, I was trying to wrap part of the program in an Iterator for the silly reason that it made logical sense. Java won't let you add checked exceptions when you're implementing an interface, so I couldn't just propagate the checked exceptions knowing they didn't actually happen.

I ended up with some dead code to satisfy the compiler, a lot of try/catch blocks covering different levels of nesting (if it fails in the outer loop, continue the outer loop; if it fails in the inner loop . . .) and pre-fetching to make sure that next always worked when hasNext was true.

Basically, several rules of Java that are supposed to stop things from going wrong actually helped them go wrong and then got in the way of fixing them.

Sunday, September 16, 2007

Stack

Today's assignment is stack. My stack is here.


Results

All five tasks completed successfully.

Problems

I had the same problem that Randy had with eclipse not finding classes. Thanks to Randy, it was easy to fix.

Thanks also to Jianfei Liao for pointing out that we might be expected to explicitly check for an install of JavaNCSS, even though a proper check is redundant to trying to use it.

I added the check in case it's required, but I still think it's bad. That kind of redundant checking can confuse people.

The most interesting thing I did was for the code coverage. I did add unit tests, but I also changed some of the non-test code.

ClearStack had a method called getTop that did nothing except call the method top inherited from Stack. So I changed it to be a single method defined in Stack and used directly without re-definition in ClearStack (just like push and pop). I wasn't sure whether the combined function should be called top or getTop, but I decided that getTop was more conventional. Coverage improved significantly.

Then I added a test to make sure that getTop throws an exception if the stack is empty. I also expanded the "normal" test to check getTop on a one-item stack and Stack.toString on empty and three-item stacks. That brought it to 100%.

Ant

Ant is a nice tool, but I think it sometimes tries to do too much.

It also has few rough edges. For example, if you try to expand a property it doesn't recognize, it silently uses the unexpanded form. That gives you things like:

[echo] PMD found ${pmd.failure.count} problem(s). 

Standards

I understand the motivation for the build file structuring, but I'm not pleased with it. What I'd like to do (but didn't) is:

  1. Rename build.xml to compile.build.xml (and update all the import references).
  2. Rename verify.build.xml to build.xml.
  3. Import dist into the new build.xml.

That wouldn't make any of the files harder to understand. In fact, the new build.xml would be easier to understand than the old one. But it would make everything a lot easier. You'd do ant to verify, ant dist to make a distribution, ant pmd to run just PMD, etc.

JavaNCSS vs. SCLC

I prefer JavaNCSS. It was easier to get useful information out of the JavaNCSS output. It only looks at the Java code, but it looks at it in much greater depth. The SCLC output left me wondering "OK, what do I do with that?" It's also nice to have the cyclomatic complexity.

The non-comment line counts don't match, and I think that JavaNCSS might be excluding blank lines while SCLC is including them. That would be another plus for JavaNCSS.

Tuesday, September 4, 2007

Code Ruler Redux

Today, we have Code Ruler Redux. My ruler was reviewed by Randy Cox, and I have a revised ruler here.


Team Member

Brian Jaress

Style Changes

First, of course, I fixed the class coding standards violations that Randy found.

I also changed some of the code to make better use of Java 5 features. In a couple places I'd been looping over an array and adding every element to a Set, and I changed it to a one-liner using Arrays.asList() and addAll().

Strategy Changes

I also made some adjustments to the strategy, adding a target minimum number of peasants and always attacking enemy knights when there are no other enemy pieces. That took care of two edge cases that came up surprisingly often.

Here are the updated test results against built-in rulers:

Migratingjaress
1773
0781
0783
Gang-upjaress
176668
162701
80732
Split-upjaress
180654
148653
202610

Shaoxuan Zhang, whose ruler I reviewed, checked the code of successful rulers from another school and adapted them into something that sounds similar in spirit to my strategy: figure out what types of targets you want to attack and have each knight attack the closest one.

It's not quite the same, though. His ruler attacks castles first, then attacks knights and peasants once it has all castles. My ruler attacks castles, peasants, and weak knights first. When all of those are gone, it attacks strong knights.

Lessons Learned

Arrays.asList() is a very handy function static method, and Eclipse is a lot easier now that I've hooked up my mouse.

I also realized that my ruler is evil.

Of course, all the rulers try to kill off enemy pieces and squeeze out other rulers, and my ruler isn't the most aggressive or effective. If, however, you think of the strategy as representing the behavior of an actual person, my ruler is the worst thug.

The other rulers seem to have either sophisticated strategies that optimize the local behavior of their pieces (Ben Karsin's ruler is a good example) or simple strategies like "capture the castles" or "split up into groups." My ruler's simple strategies are "target the weak" and "don't let anyone have a bigger army." Even the peasant strategy, which I think is quite effective, leads to a creepy "peasant Matrix' effect.

Saturday, September 1, 2007

Code Ruler Review

Today's assignment is Code Ruler Review. I'm reviewing the code of Shaoxuan Zhang.


Overall Impressions

A little dense in places, but generally well written. The strategy was clear and sensibly implemented.

I noticed that English does not seem to be Shaoxuan's first language. I had no problem understanding the comments, but the type of grammar tweaking that the rules insist on seemed rather pointless. I think maybe those rules should be relaxed in this case (but I listed them anyway).

The number of things to fix was surprisingly low, considering it was written before we got the rules.

Standards Check

Entries in the "Lines" column refer to the MyRuler.java file.

LinesRuleRule Description
ICS-SE-Java-0Follow EJS standards.
1ICS-SE-Java-1All code is within the package hierarchy "edu.hawaii".
1ICS-SE-Java-2Do not use the wildcard "*" in import statements.
ICS-SE-Java-3Only one Java statement per line.
ICS-SE-Java-4Do not include // comments at the top of the file.
ICS-SE-Java-5Rewrite default Eclipse template JavaDocs to be useful.
ICS-SE-Java-6Format JavaDoc summary lines correctly
ICS-SE-Java-7Do not use Vector and Hashtable classes.
ICS-SE-Java-8Do not use "raw" Collections classes
ICS-SE-Java-9Prefer the for-each control structure to the for control structure.
ICS-SE-Java-10Use the @Override annotation when overriding equals() and hashCode
ICS-SE-Eclipse-1Use Eclipse Europa 3.3
*ICS-SE-Eclipse-2Import and use the Eclipse Java Code formatting template.
ICS-SE-Eclipse-3Configure Text Editor.
EJS-1Adhere to the style of the original.
EJS-2Adhere to the Principle of Least Astonishment.
EJS-3Do it right the first time.
EJS-4Document any deviations.
EJS-5Indent nested code.
EJS-6Break up long lines.
EJS-7Include whitespace
22,23,24,*EJS-8Do not use "hard" tabs
EJS-9Use meaningful names.
EJS-10Use familiar names.
EJS-11Question excessively long names.
EJS-12Join the vowel generation.
EJS-13Capitalize only the first letter in acronyms.
EJS-14Do not use names that differ only in case.
EJS-15Use the reversed, lowercase name of your organization's Internet domain name as the root qualifier for your package names.
EJS-16Use a single, lowercase word as the root name of each package.
EJS-17NOT USED
EJS-18Capitalize the first letter of each word that appears in a class or interface name.
EJS-19Use nouns when naming classes.
EJS-20Pluralize the names of classes that group related attributes, static services or constants.
EJS-21Use nouns or adjectives when naming interfaces.
EJS-22Use lowercase for the first word and capitalize only the first letter of each subsequent word that appears in a method name.
157EJS-23Use verbs when naming methods.
EJS-24Follow the JavaBeans™ conventions for naming property and accessor methods.
EJS-25Use lowercase for the first word and capitalize only the first letter of each subsequent word that appears in a variable name.
EJS-26Use nouns to name fields.
EJS-27Pluralize the names of collection references.
EJS-28Establish and use a set of names for trivial "throwaway" variables.
92,96,100,*EJS-29Qualify field names with "this" to distinguish them from local variables.
EJS-30When a constructor or "set" assigns a parameter to a field, give that parameter the same name as the field.
EJS-31Use uppercase letters for each word and separate each pair of words with an underscore when naming constants.
EJS-32Write documentation for those who must use your code and those who must maintain it.
EJS-33Keep comments and code in sync.
12EJS-34Use the active voice and omit needless words.
22,28EJS-35Use documentation comments to describe the programming interface.
EJS-36Use standard comments to hide code without removing it.
32,36,40,*EJS-37Use one-line comments to explain implementation details.
EJS-38Describe the programming interface before you write the code.
91EJS-39Document public, protected, package, and private members.
EJS-40Provide a summary description and overview for each package.
EJS-41Provide a summary description and overview for each application or group of packages.
EJS-42Use a single consistent format and organization for all documentation comments.
EJS-43NOT USED
EJS-44Wrap code with <pre>...</pre> tags.
EJS-45Consider marking the first occurrence of an identifier with a {@link} tag.
EJS-46Establish and use a fixed ordering for Javadoc tags.
125,150,198,*EJS-47Write in the third-person narrative form.
8,124,149EJS-48Write summary descriptions that stand alone.
124,149EJS-49Omit the subject in summary descriptions of actions or services.
8EJS-50Omit the subject and the verb in summary descriptions of things.
10,152EJS-51Use "this" rather than "the" when referring to instances of the current class.
EJS-52Do not add parentheses to a method or constructor name unless you want to specify a particular signature.
EJS-53Provide a summary description for each class, interface, field and method.
91EJS-54Fully describe the signature of each method.
EJS-55Include examples.
EJS-56Document preconditions, postconditions, and invariant conditions.
EJS-57Document known defects and deficiencies.
EJS-58Document synchronization semantics.
EJS-59Add internal comments only if they will aid others in understanding your code.
EJS-60Describe why the code is doing what it does, not what the code is doing.
172,187,205,*EJS-61Avoid the use of end-line comments.
EJS-62Explain local variable creations with an end-line comment.
EJS-63Establish and use a set of keywords to flag unresolved issues.
EJS-64Label closing braces in highly nested control structures.
EJS-65Add a "fall-through" comment between two case labels, if no break statement separates those labels.
EJS-66Label empty statements.
EJS-67Consider declaring classes representing fundamental data types as final.
EJS-68Build concrete types from native types and other concrete types.
EJS-69Define small classes and methods.
EJS-70Define subclasses so they may be used anywhere there superclass may be used.
55,59,63,*EJS-71Make all fields private.
EJS-72Use polymorphism instead of instanceof.
EJS-73NOT USED?
EJS-74NOT USED
EJS-75Replace nontrivial expressions with equivalent methods.
105,109,132,*EJS-76Use block statements instead of expression statements in control flow constructs.
EJS-77Clarify the order of operations with parentheses.
EJS-78Always code a break statement in the last case of a switch statements.
EJS-79Use equals(), not ==, to test for equality of objects.
EJS-80Always construct objects in a valid state.
EJS-81Do not call nonfinal methods from within a constructor.
EJS-82Use nested constructors to eliminate redundant code.
EJS-83Use unchecked, run-time errors to report serious unexpected errors that may indicate an error in the program's logic.
EJS-84Use checked exceptions to report errors that may occur, however rarely, under normal program operation.
EJS-85Use return codes to report expected state changes.
EJS-86Only convert exceptions to add information.
EJS-87Do not silently absorb a run-time error exception.
EJS-88Use a finally block to release resources.
EJS-89Program by contract.
EJS-90NOT USED
EJS-91Use assertions to catch logic errors in your code.
EJS-92Use assertions to test pre- and post-conditions of a method.
EJS-93Use threads only where appropriate.
EJS-94Avoid synchronization.
EJS-95Use synchronized wrappers to provide synchronized interfaces.
EJS-96Do not synchronize an entire method if the method contains significant operations that do not need to be synchronized.
EJS-97Avoid unnecessary synchronization when reading or writing instance variables.
EJS-98Consider using notify() instead of notifyAll().
EJS-99Use the double-check pattern for synchronized initialization.
EJS-100Use lazy initialization.
EJS-101Avoid creating unnecessary objects.
EJS-102Reinitialize and reuse objects to avoid new object construction.
EJS-103Leave optimization for last.
EJS-104Place types that are commonly used, changed, and released together, or mutually dependent on each other into the same package.
EJS-105Isolate volatile classes and interfaces in a separates packages.
EJS-106Avoid making packages that are difficult to change dependent on packages that are easy to change.
EJS-107Maximize abstraction to maximize stability.
EJS-108Capture high-level design and architecture as stable abstractions organized into stable packages.

Wednesday, August 29, 2007

Code Ruler Results

Today's assignment is Code Ruler. My code is here. (The zip file contains the entire project, plus javadoc documentation. I had to change Code Ruler's default project settings to get the Java 5 features to compile.)


Group Member

Brian Jaress

Evaluation Results

Migratingjaress
14733
14717
0792
Gang-Upjaress
382583
245592
291543
Split-Upjaress
318328
349502
440269

Lessons Learned

I learned a bit more about Java, especially Java 5. Mostly I re-learned the lesson that code should only be written when you know you need it.

I'm also slowly getting used to the tools -- forcing myself to only edit the code in Eclipse and learning a few javadoc quirks. I managed to download and import our formatting rules for Eclipse, so my code should be nice and standard (except that I edited the rules to change the line width from 100 to 72 characters. There are standards, and there are standards.)

Sunday, August 26, 2007

Assignment 02: ConsultComm

Today's assignment is to evaluate an open-source Java project on Sourceforge according to our Three Prime Directives.


Overview

ConsultComm is timekeeping program. It helps you keep track of what you have been doing and how long each thing took. From its website:

ConsultComm is a small, lightweight, platform-independent program written in Java that allows anyone managing multiple projects, clients or tasks to effectively keep track of exactly how long they've worked on each project.

-- http://consultcomm.sourceforge.net/

ConsultComm does a good job of satisfying Prime Directive 1, but it is less successful with Prime Directives 2 and 3.

Useful Task

Keeping track of time spent is a useful task, and ConsultComm does that successfully. You can have several tasks in groups, each listed with the time spent so far. There's a built-in timer that you can start and stop which credits time to the currently selected task.

Installation and Use

A typical user could install this program successfully.

An installer is available as a jar file, created using IzPack. It is a typical wizard-style installer, though there is a slightly confusing option at the end about "targets." (It can be ignored.)

Some users might not be able to successfully use ConsultComm. The interface is simple but a little tricky, and there is no user documentation.

The easiest, most prominent feature is a button which starts and stops a timer. If you use that feature first, it will appear to be doing something while actually doing nothing. Before you use the counter, you have to create a project so that the time elapsed will be recorded somewhere rather than thrown away.

You can create projects using a menu or a keyboard shortcut. It's fairly easy once you know that it's what you need to do. If you've used the default install, it also asks about JDBC exports. You can ignore that and hit "save."

Improvable

A determined outside developer could probably contribute to ConsultComm.

The current development branch is in the Subversion repository at https://consultcomm.svn.sourceforge.net/svnroot/consultcomm/trunk, and the developer documentation is in the form of javadoc comments.

It takes a little while to figure out how the program is organized. For example, everything except the updating of the current project's time on a clock tick is done through JavaBean event listeners. (The main window registers as a listener for the clock and responds to the event by finding the currently selected project and directly changing its time.)

Wednesday, August 22, 2007

Assignment 04

Today's assignment was FizzBuzz.

The Experience

It took a total of eleven minutes from the time I launched Eclipse to the time I was satisfied that the program produced the right output.

The single biggest step was checking the output (and I didn't check all of it). As a category, figuring out how to do things in Eclipse took the most time. I spent some time walking slowly through the wizards for starting a project and class, reading it all to figure out what information I was supposed to give it.

Then I spent a big chunk of time figuring out how to run a program from inside Eclipse to test it. Once I got it to run, I could run it again by clicking the "run" button or the Run -> Run.. menu item, but the first time I had to try a couple different things before Eclipse realized that my class was a program.

The time for actually writing the code was probably shortened by the fact that we wrote out the program on paper in class yesterday.

The Code

This is with Eclipse's default indentation. I gathered from class that we will use a different One True Way, but we haven't learned it yet.

public class FizzBuzz {
        public static void main(String[] args) {
                for (int i=1; i<101; i++) {
                        if (i % 5 == 0 && i % 3 == 0) {
                                System.out.println("FizzBuzz");
                        } else if (i % 3 == 0) {
                                System.out.println("Fizz");                       
                        } else if (i % 5 == 0) {
                                System.out.println("Buzz");                       
                        } else {
                                System.out.println(i);                                                 
                        }
                }
        }
} 

The Lesson

Anything we learn, we're going to learn the Java way.

I'm a little worried that this class will turn into "Java for Enterprise Development" with actual software engineering taking a back seat.

I still have my undergraduate software engineering textbook. Chapter sixteen covers object oriented design, including a brief introduction to Java.

Tuesday, August 21, 2007

Engineering Log

This is a special-purpose blog. It will serve as my required engineering log for ICS 613 in Fall 2007. (Creating a blog on Blogger is one of our assignments.)

For anything not related to that class, you can find me at my personal blog.