Dr. Hacker (February, 2002)
Home Schedule Prime Directives Engineering Log Coding Standards Software Submission Checklist Dr. Hacker

 

2/1/2002

> Dr. Hacker,
>
> I remembered you mentioned that the next assignment is cleaning up our
> code and I saw in your shedule next wednesday is also review day.
>
> What time is the due date for the cleaned up edition?
>
> - Sleepless in Salt Lake
[Dr. Hacker looks up, puffy eyed, from the 100 MB of AccountInfo code he is slogging through to provide this reply.]

Good question. Here's how I think the next couple of weeks are going to go.

2/4: This will be a lecture on configuration management and an introduction to CVS. On that day, you will also need to split into groups of two for the next assignment. (You will form *different* groups of two for each assignment, so this is just a temporary partner. Don't get all stressed about getting your best friend to work with, because you'll have to change in a couple of weeks.) Feel free to arrange your partner before class. Anyone who isn't partnered up voluntarily on 2/4 I will assign to a partner on that day.

2/6: On this "review day", I will go over my "Lessons Learned" from review of your code, and introduce new requirements for the second version of AccountInfo. This will be the day that the next assignment is formally released. You will have one week to complete it, you will probably tear apart the two solutions from each partner and integrate the best of both into your next version, and you will work in pairs. (And, you will use the CVS repository.)

2/11: And, you will also use JUnit, after having listened to my wonderful lecture on the subject. Some of you have simply gone ahead and learned to use it on your own, which is great. (And which is the way 98% of all JUnit users have learned to use it, so you're not alone.) If you've written tests some other way and have the rest of the assignment completed by today, then 48 hours should be enough time for two of you to convert to JUnit.

2/13: This was a "catch up" day, but will now be a "review day", in which I will download your version 2 assignments from the CVS repository in class and build them and review them.

And then next week we have a holiday and a midterm. The fun just never stops in this class, doesn't it?

Cheers, Dr. Hacker

2/3/2002

> Dear Dr. Hacker,
> 
> As I mentioned to you in class... I tried to use several int constants in my
> User class, generally:
> 
>    private final int MIN_PASSWORD_LENGTH = 6;
>    private final int MIN_UPPERCASE_COUNT = 1;
>    private final int MIN_LOWERCASE_COUNT = 1;
>    private final int MIN_NUMERIC_COUNT = 1;
> 
> and CheckStyle bounced it citing a failure to match the regex:
>      ^[a-z][a-zA-Z0-9]*$
>
> What's wrong?
>
> -- Checkmate
This is an interesting question, because the following code in the Stack example passes checkstyle:
  public static final String STACK     = "Debug.Stack";
A couple of experiments showed me that it was the presence of the 'static' keyword that made my uppercase variable name copacetic to checkstyle. At that point, I decided to RTFM. What I found out is that Checkstyle allows you to specify patterns for the following:
static and final
static only
non static
non static public
What is conspicuously missing is 'final only', which is the kind of variable you were defining above. This leads us to the question of whether or not the Elements of Java Style rule #31 applies only to static final constants (which is the kind they illustrate), or whether a private non-static constant should also follow that convention.

For the time being, let's answer it by following Checkstyle's lead and say that the upper case rule only applies to static final constants. A private constant should be named according to regular variable conventions.

> Dear Dr. Hacker,
> 
> I am wondering whether you are willing to provide source code for the
> j2htaskdef.jar file, which is apparently developed in your csdl lab.
> 
> -- Potential Ant Task Hacker
Absolutely. As soon as you have obtained your CVS account and password (which will be handed out tomorrow in class), you'll be able to do a cvs checkout of the module 'j2htaskdef' from the repository.
> Dr. Hacker,
>
> As a time-use note, even though there's no current programming assignment
> that fact that I need to catch up with reading assignments still cuts into
> time for other work.  It may be that I read more slowly than other students
> --- but I don't have time to read/absorb everything you are posting.  I think
> it might help to prioritize what you're telling students to look at and do,
> so they know which things you consider most important, and which are
> expendable.
>
> -- Software engineering is harder than I thought!
Sorry to depress you further, but for each assigned reading in the class, I have typically cut out several additional related readings that would be useful. So, unless I specifically flag a reading as "optional", every reading assignment is important and not "expendable". Some reading assignments (such as the 613 textbook stuff) is a kind of "forward reference"---the value of it won't come until a certain critical mass of material has been read, but I am spreading the material out so that I don't have to hit you with 6 chapters in a single week.)

On the other hand, I am aware that learning to actually develop software using high quality software engineering principles is much harder than it appears, and that many of the things you are reading for the first time in this class are things that require reading and re-reading over a period of time to fully appreciate and absorb.

So, I suggest the following: (a) First, you simply have to *make* the time to read everything I assign in a timely manner. If you are a slow reader, then it will take you longer. (b) Second, depending upon your java background and intellectual readiness for the material, a reading assignment will be 'absorbed' to a greater or lesser extent. Some things may not "make sense" to you if you have not had certain kinds of software development experiences. That's just inevitable, so don't freak out if you don't immediately feel like you "get" every single idea in every single reading. However, if you have read the material, then it is my belief that at some point in the future, when you encounter the situation, you will remember that you read something about it and be able to go back and re-read the material, this time understanding it more deeply.

Cheers, Dr. Hacker

2/7/2002

> Dear Dr. Hacker
>
> I want to use the Regexp jar file. My accountinfo1 software works in JBuilder
> but ant  doesn't seem to find the library. I copied it into
> ./lib/ant1.4.1/lib as suggested. But ant gives me an error message:
> java.lang.NoClassDefFoundError: org/apache/regexp/RESyntaxException
>
> Do I have to add an entry into build.xml so ant uses the Regexp library? Or
> should it work automatically?
>
> - All jarred up and no place to go
Remember how I said in class that to add third party applications to your system, all you have to do is drop them into lib/ant1.4.1/lib and Ant would find them automatically, eliminating the need to manually edit a classpath? Well, I lied. A little.

The reality is just a tiny bit more complicated. It is true that Ant *does* add all of the jar files in its lib directory onto its classpath. Thus, I am confident that the compile task succeeded without a problem. I think the problem actually came up during the test task, and the reason it came up here is because the test task calls the JUnit task, and the JUnit task *forks* a new java subprocess. If you read the code in the Ant build.xml file, you'll see both a "fork=yes" parameter and a junit.classpath property. That's because when Ant (or, more accurately, JUnit) forks the subprocess, the subprocess does not inherit the classpath that Ant was using. That may be a bug, or it may be a feature, I'm not sure.

So, there's two ways to solve this problem. First, you can say "fork=no", which changes the JUnit task to run inside of Ant, which will provide it access to all of the jar files in the lib/ant/lib directory. It will also speed up your test case processing. The other thing you can do is modify the junit.classpath property in the build.xml file and add the required jar files so that the junit subprocess can find them when it runs.

> Dear Dr. Hacker,
>
> You said this Monday in class that when importing files
> the csh and ant files should be "force binary". Why
> should we do that?
>
> - To force, or not to force, that is the binary question
Long ago, for some mischievous reason, the designers of the Unix, Macintosh, and Windows platforms agreed to disagree on the matter of line termination characters. This has caused pain and suffering for generations of cross-platform programs (and programmers) ever since.

Which brings me to the pain of forcing binary. The .csh and ant files are intended to be run on Unix. CVS, when importing these files, will automatically convert the line endings to the windows version unless binary is specified. So, by specifying binary, we force CVS to leave the files alone and in their Unix-compatible format.

> Dear Dr. Hacker,
> 
> Synchronize our time with CVS server needs the server identifier
> and DNS name of IP address it (and maybe some other parameters
> that you point out to me). Can you provide this information
> to the class?
> 
> -- Time keeps on slippin, slippin, slippin, into the future
No, I don't need to. If you're using YATS (which your subject line indicated), you can just use the default Internet time servers. The idea is not for all CVS clients to be synchronized with the CVS server's time clock, its for the CVS clients and servers to be synchronized to an Internet time server (which implicitly synchronizes them to each other.)
> Dear Dr. Hacker,
> 
> Let me ask a few questions about assignment2;
> 
> 1. Can all existing user change own user ID? Or can only admin user
> change user IDs?
> 
> 2. Can a user (student, faculty) delete own account?
> 
> I think that user ID can not be changed and deleted except admin user.
> What do you think?
This is an interesting and astute question. Ultimately, we may well want to represent the "role" of the client of the AccountInfo class in some sense, and make sure that they are authorized for the particular operation. However, that goes beyond the scope of the current Account Info package. Assume that if a client invokes an operation on Account Info, then it's because they've been already authorized by some other mechanism to do so.

BTW, I've had a very interesting conversation with a Professor Poi this morning about the requirements for this assignment and the direction of the course. The transcript of the interview is available from Dr. Hacker page on the web site:

http://csdl.ics.hawaii.edu/~johnson/413s02/dr__hacker.htm

I think everyone will benefit from reading it. Please do so before the next class and come with questions.

Cheers, Dr. Hacker

2/12/2002

> Dear Dr. Hacker,
> 
> I have a question, but don't laugh.. i took a look at the sample programs
> that were posted.. i noticed a tiny, tiny detail here it is:
> 
> in qzhang's AccountInfo class, this person named methods with "Account"
> concatenated to the action.  For example, "addAccount".  However, in wdoane's
> AccountInfo class, this person named methods with just "add".  Which one is
> correct?  I am thinking "add" is correct because the java collection
> framework classes uses the same convention.
> 
> this is just something i noticed and i was wondering if it made any
> difference...
> 
> thanks,
> -- details, i want details... haha..
I'm not laughing at all, in fact, I commend you for noticing one of the subtleties that separates the hacker who truly knows Java from those with a superficial acquaintance with the language.

Obviously, to the computer, what you name the add method doesn't make any difference at all. However, from a readability and understandability perspective, it can make a substantial difference. There are many naming conventions observed in the Java API, and when you as a programmer design software that conforms both to the naming conventions and the underlying semantics that they represent, then everyone wins.

In this case, if the AccountInfo add method is, for example, essentially "passing through" to an underlying add method from the Java Collections Framework, then I would agree that using "add" is the best choice; it gives the programmer who knows the collections API the best insight into what the method is doing. On the other hand, if the add method has a behavior quite different from the collections API add method, then it would be misleading to name it the same.

> Dear Dr. Hacker,
> 
> Our group has two ways of implement accountinfo, we would like to know
> which one is better. Also, we would like to know if a setAccountName
> method is necessary because we use the account name as the key to
> add an account to the collection so changing the value of the key does
> not seem to be a desirable action.
> 
> Our main question here is: what is the AccountInfo class suppose to be? Is
> it a container class or is it a class that use to implement the Account
> class.
> 
> 1)
>   Account is created in TestAccountInfo class and being added to the
> collection by calling the addAccount method in the AccountInfo class
> therefore before an account is created we must check for valid accountname
> and password so all the checking is being done in the Account class.
>   The reason for this design is because AccountInfo is meant to be a
> container only therefore all the methods in AccountInfo are for putting in
> and taking out account objects from the collection.
> 
> 
> 2)
>   Account class represents an account object therefore Account class has
> only the methods to set and get the informations about a particular
> account such as password, firstname, lastname, accountname, and email.
>   All the checking for valid accountname and password is done in
> AccountInfo class before an account is created. Accounts created must have
> an account name and password but firstname, lastname, and email can be set
> later.
>   The reason for this design is so that in the future is the
> specifications for accountname and password is changed all we have to do
> is make changes to the AccountInfo class and don't touch the Account class
> to prevent unnecessary mistake from occurring when modifying.
> 
> --  Caught between the horns of a programming dilemma
I've had a couple of groups ask me about the setAccountName method. In the cases I've seen so far, since it is being used as a primary key, it can make abundant sense to prohibit that action. (If someone wants to change their account name, then they have to delete the old account and establish a new one).

The second question is whether to attach constraints regarding accounts (such as password validity) to accounts, or to attach them to something else entirely (such as the account container). I think you're better off attaching constraints regarding accounts to the account class. Your rationale for attaching it to the container class makes no sense to me: either way, you're going to end up modifying something. Either way, if you make a mistake, you've got problems.

> Dear Dr. Hacker,
> 
> I am unsure on how to achieve the 1 test case density per 10-15LOC.
> Suppose I have a test method so that it tests both correct and incorrect
> input--should I split it up into two methods so that one tests correct
> input and the other incorrect input?  If so, should I split these tests
> even further so that each method tests each unit test design heuristics
> (refer to slide 21 of 'Concepts of Testing').  If done that way, then I
> will achieve 10 different test methods.  If I apply this to each method in
> accountInfo class alone, I will have 30 test cases altogether!
> 
> Is this okay?
> 
> -- Bean counting
Sigh. The problem with metrics is that well-intentioned hackers try to follow them and screw up perfectly good programs in the process :-).

All levity aside, the (understandable) misunderstanding is that the term "test case" from the JUnit perspective (a class which extends TestCase) does not necessarily mean the same thing as the term "test case" from the article you are quoting.

In JUnit, you can think of "test" at three levels of granularity: (1) the class, (for example, TestLoginCommand); (2) one of the potentially many test methods within that class (such as testSuccessfulLogin); and finally (3) one of the potentially many assert calls within any of the many test methods (such as assertSame(..)).

My view is that you should design your set of test classes, methods, and assert calls in the most natural and efficient manner for your application and don't worry about acheiving some artificial metric. There are situations when I'm writing a test case where the most natural approach to me is to have 15 assert calls within a single test method, and that's the only method within the class. So, do I have 15 tests, or one test? At the end of the day, I don't really care; what I care about is that I have exercised my software in such a way that I feel confident that it's working now and that if I make a change in the future and then run this test again, I will feel confident that my change didn't break it.

If you're still interested in your compliance with the recommended "test density" of 1 test per 10-15 LOC, I would recommend that you define each call to assert as a separate test, and not worry about whether they are each in individual methods or all together in one.

> Dear Dr. Hacker,
> 
> Do you mean we must use assertSame instead of assertTrue otherwise you'll
> grade down?
> 
> -- Still hoping my future employer will care about my GPA
Grading down is a distinct possibility, but I hope that you're really more concerned about the best thing to do. Remember that a central property of a "test" is the comparison of an expected value with an actual value. The assertSame method does a much better job of articulating what the expected vs. actual values are than assert true. For example:

assertTrue ("Testing foo vs. bar", foo() == bar())

Tell me, which is the expected and which is the actual value here? Furthermore, when this fails, all JUnit will report is the following:

Testing foo vs. bar failed

Contrast that with:

assertSame ("Testing foo vs. bar", bar(), foo())

Here, we know by the order of the arguments that the value of bar() is the expected (correct) value, and the value of foo() is that actual (test) value. Furthermore, JUnit knows that as well, so if this test fails, it can say something much more informative like:

Testing foo vs. bar failed, expected: 34, actual: 33

There are a few situations where assertTrue is the most appropriate choice, for example, when your test is to invoke a predicate that returns true or false as its value:

assertTrue("Checking too short password", !Account.isValidPassword("foo"));

> Dear Dr. Hacker,
>
> ah man... I can't get JUnit to work.  Anybody else having troubles?  I
> tried running the test programs and...
> 
> C:\>java junit.textui.TestRunner junit.samples.AllTests
> Class not found "junit.samples.AllTests"
> 
> I even tried running AllTest directly, but it keeps saying the the
> AllTests class doesn't exist.  I don't get it cause it's right fricken
> there in front of my face.  arggggg...
> 
> Something is wrong with the path.  Even when I run ant on my accountinfo1
> project it can't find the junit directories...
> 
>     [javac]
> E:\cvs413\accountinfo\build\src\edu\hawaii\accountinfo1\Te
> tAccountInfo.java:30: cannot resolve symbol
>     [javac] symbol  : method fail  (java.lang.String)
>     [javac] location: class edu.hawaii.accountinfo1.TestAccountInfo
>     [javac]       fail("Duplicate account name test FAILED!\n");
> 
> 
> Any help would be appreciated.  I've been reading the README file for
> JUnit over and over and I can't figure it out.  Google.com didn't help me
> much either.
> 
> -- I'm tense and nervous and I can't relax
The most important, useful, and helpful thing I can say is the following:

Why didn't you send this email last week?

What's going to happen now is that you're going to have a very unhappy day trying to work through an absolutely show-stopping bug. And because the clock is ticking, you're going to be under pressure. And because you're under pressure, you're not going to think as clearly. And because you're not going to be thinking as clearly, it's going to take you longer to figure things out. And because it's going to take you longer to figure things out, the clock is effectively ticking faster than normally. And because the clock is ticking faster than normally, you're going to be under more pressure.

And so forth.

Folks, please don't wait until the last minute to start these assignments. I don't like inflicting pain. I don't intend to inflict pain. It's not necessary to feel pain. Well, maybe it is necessary to feel a little pain, as long as you learn from it.

Anyway. Let me suggest the following. First, login to CVS and check out the stack module. cd into that directory, and type setenv. Then build and test the project. Is everything OK? If so, then you're 99% done solving the bug, because you now have one system installed on your computer that compiles successfully, finds JUnit, and executes the test methods, and another system installed on your computer that doesn't. Therefore, there is a difference between these two systems, and all you have to do is figure out what it is. If it were me, I would start by comparing the two build.xml files. If those are OK, I would then compare the contents of the lib/Ant1.4.1/lib directory. If those appear to be OK, then I might try doing a jar -tf on the junit.jar file (to make sure that you uploaded it as binary). Then I would move on to comparing the source files. Eventually, you'll figure it out. Whether that happens by tomorrow is the worrisome issue at this point, of course.

> Dear Dr. Hacker,
>
> My AccountInfo remove method only throws an exception when the
> account doesn't exist.  Do you feel that checking if the collection is
> empty should also be checked here?
> 
> -- Running on empty
At a more general level, what you're asking is: should it be considered an error to have a container of accounts with no accounts in them?

I think it should be pretty clear that the answer to that is No. There's nothing semantically invalid about an account container with no accounts in it. Indeed, that might be an important capability to some applications.

Since there's nothing semantically invalid with an empty account container (just like there's nothing semantically invalid with an empty ArrayList or an empty HashMap), there's nothing wrong with asking whether an account is present in a container which just happens to have no accounts in it at all. The answer will be negative, but no exception should be thrown.

Cheers, Dr. Hacker

2/15/2002

> Dear Dr. Hacker,
>
> I found something weird for javadoc.
> I removed and deleted a class from my java source package.
> But when I run ant javadoc, the API for that class still there even I
> delete api folder and run it again. I can't find the place that let me
> change something to fix this problem. Could you tell me how should I do?
Yes. Run 'ant clean' first.
> Second question is about style. I found some of the rules in "Element of
> Java Style"
> is not consistent with pretty print enforcement. For ex. pretty print
> enforce
> if ... else as
>                        if (..) {
>                          ...
>                        } else {
>                          ...
>                        }
>
>  and  try and catch as
>                       try (...) {
>                          ...
>                       } catch {
>                          ...
>                       }
>
> Could we view this as the right style? Thanks.
>
> -- Wondering what the Java equivalent of 'triple axle' is...
No, you can't view those as the right style. What you have to do is modify the default settings for the JRefactory pretty printer so that it formats code according to our style guidelines. Choose "Pretty Printer Configuration" from the JRefactory menu and spend some time with the ensuring window. With just a little tweaking, you can get the pretty printer to produce compliant formatting.

Cheers, Dr. Hacker

2/26/2002

> Dear Dr. Hacker,
>
> I was playing around with the stackMVC system and I ran junit on it and it
> seems that all the junit test fail...  Did i do something wrong?? it is kind
> of funny cause the system does work in on tomcat.  any ideas?
>
> - Test failures? What, me worry?
Yes, something is wrong. I have a couple of suggestions. First, it seems clear that while you did observe that the tests failed in the command shell, you didn't take the next logical step and look at the actual test report! Go into your browser, open the README, and click on the link to the test results page. I would not be surprised if reading the test report failure information provides you with insight into what went wrong. (And, of course, if it doesn't, then including that information in emails to me regarding JUnit failure will enable me to help you much more effectively. As a general rule, whenever anyone is asking for information about JUnit test failure, it's a great idea to provide the JUnit test report results.)

My second suggestion is to inspect your TEST_HOST environment variable. When the system appears to work fine manually but *all* of the test cases fail, then that often indicates a generic problem with the test environment setup. In this case, one possible problem is that TEST_HOST is not set correctly or not at all. If so, the JUnit test report output should lead you to that.

> Dear Dr. Hacker,
>
> Is there any good documentation on the "c" prefix taglib?  I can't seem to
> find any helpful information on it.
> 
> -- Tag team hacker
Try http://jakarta.apache.org/taglibs/doc/standard-doc/intro.html
> Dr. Hacker,
>
> The way to change the JDK in JBuilder PE is...
> 
> Tools menu, Configure JDK.  Change the JDK path to the JDK you want to use.
> I just changed the path to the standard JDK path, but didn't test it.  All
> the directories are the same, so I don't think there's likely to be a problem
> with it.
>
> -- Two JDKs are better than one
Thanks for the info. I've been thinking about this issue more, and I'm increasingly worried about the implications of everyone randomly upgrading to different versions of Java and submitting their assignments with potentially jdk-specific binary or source code. (I had to deal with this to a minor extent last semester and it was a colossal pain.)

So, here's the deal. The *standard* jdk for this semester is jdk 1.3. That's the one I intend to always use for grading and evaluation of projects. Therefore, everyone is responsible for making sure your projects run with jdk1.3. If you've upgraded to 1.4 and deleted your 1.3 version, you probably want to back down to 1.3 or at least keep both versions available.

At some point, if we decide we really want to use built-in assertions, logging, regular expressions, and so forth, then we can decide as a group to simultaneously upgrade to jdk1.4, and that would be OK. But all our lives will be simpler if we all use the same version of Java, and for now, that version has to be 1.3.

Cheers, Dr. Hacker

2/27/2002

> Dear Dr. Thinga-mo-bob-
>
> I believe I've found an error in you setEnv.csh and intend to take 5 points
> off of your grade for this submission.
>
> In the following from your setEnv.csh included with the stackmvc1.0225:
>
> # Set up OPTS variables.
> setenv STACKMVC_OPTS "-Dcatalina_home=$CATALINA_HOME -Dtest_host=$TEST_HOST"
>
> setenv ANT_OPTS "$STACKMVC_OPTS $ANT_OPTS"
> setenv CATALINA_OPTS "$STACKMVC_OPTS $ANT_OPTS"
>
>
> Shouldn't the last line above be:
>
> setenv CATALINA_OPTS "$STACKMVC_OPTS $CATALINA_OPTS"
>
> ??
>
> -- GNU's Not Unix!
Yes, of course. Dr. Hacker is mildly embarrassed for having not tested his installation package on both Windows and Unix platforms before release, but notes that "given enough eyeballs, all bugs are shallow (Eric Raymond)". I'll update the CVS repository and post a new distribution today.
> Dear Dr. Hacker,
>
> I was poking around the java.sun.com and found an interesting article from
> Borland about integrating tomcat with jbuilder:
> http://community.borland.com/article/0,1410,22057,00.html .. is it worth the
> trouble to try to do this and is it even possible with the new versions of
> the programs (apparently the article is based on tomcat 3.1 and jbuilder3.5)?
>
> -- Net surfer
First off, I think it's great that you've been "poking around". That's exactly the kind of curiosity and initiative that will keep you learning and advancing long after you don't have Dr. Hacker slapping you around with a wet servlet noodle. (And if you've ever been slapped around by a wet servlet noodle, you know how painful that can be.)

I looked at the approach, and I expect it would apply in general to Tomcat 4 and JBuilder 6, although the details (menu items, jar file names, etc.) would almost certainly differ. There is one big strength and one big weakness to this approach. The strength is that if you set it up right, you should be able to run Tomcat as a subprocess of JBuilder and thus allow you to use the JBuilder debugger on your server-side code and set breakpoints, etc. The weakness is that Ant-based deployment is much cleaner with respect to ensuring that work files are deleted, etc., and you can feel much more confident that what you're seeing is also what users will be seeing. In the end, if you feel like putting some extra work into providing an alternative development structure, by all means go ahead and fool around with this. As long as you view it as an "extra curricular" activity, it can't hurt, and you'll certainly learn some things in the process.

Cheers, Dr. Hacker

2/28/2002

> Dear Dr. Hacker,
>
> In your stackmvc, you create a StackModel instance by
> StackModel.getInstance() instead of new StackModel(). Now my question is
> when to implement a static getInstance() method to generate an object?
>
> -- I don't get it, for instance.
StackModel is an example of the Singleton design pattern. You use the singleton design pattern when you want to make sure that only one instance of a class exists and is manipulated by all clients. getInstance() is the standard name in Java for the method that retrieves a singleton.
> When i attempt to open up JBuilder 6 Personal i get the following message:
>
> Unknown license file format
>
> I cant' figure out what the problem is.  I've tried uninstalling and
> reinstalling JBuilder dozens of times.  I've called Borland
> support and they just directed me to their newsgroups with out helping me
> because i didn't purchase JBuilder.  Any ideas???
>
> - Licensed to ill
To quote an ancient hacker debugging zen koan, "Once in a while you get shown the light in the strangest of places if you look at it right." Go to google (I'm sure that comes as no surprise), click on the "groups" tab, type in "unknown license file format", and hit return. I expect you'll find the solution to your problem in less than 10 seconds. The Borland support dude was actually giving you an excellent answer because you'll find many more pearls of wisdom in the newsgroups; you just have to learn how to find them.
> Dr. Hacker,
>
> I'm working on the doubleCommand assignment and I finish the DoubleCommand
> class, but I'm working on the testing.  What are some illegal testing can
> we do?  I can't really see an illegal test because say you try to double a
> empty stack, the way my doubleCommand works is that it will double it,
> but since the stack is empty, it will just stay empty.  I tried everything
> out and it works.
>
> Also, we just do a screen dump for this assignment right?  We don't upload
> to wincvs right?
>
> - Double or nothing
The way your doubleCommand is working is not the right way according to the assignment. You have to determine if the stack is empty (now there's an interesting design question), and then set the ErrorMessage attribute.

Yes, you just do a screen dump. These minor hacks don't warrant CVS.

> Dr. Hacker,
>
> I don't if it's correct, but it seems the jdk comes with JBuilder6 is
> jdk1.3.1, not jdk1.3. This is the case for me, don't know how's other
> people. Does this matter?
>
> -- Version worries
No, that's fine. jdk1.3 and jdk 1.3.1 are close enough that there shouldn't be any configuration conflicts in this class.

Cheers, Dr. Hacker