View this PageEdit this PageAttachments to this PageHistory of this PageHomeRecent ChangesSearch the SwikiHelp Guide
Hotspots: Admin Pages | Turn-in Site |
Current Links: Cases Final Project Summer 2007

David Hendershot

Message Passing (1 point)

In Smalltalk, all computation is handled by message passing. Since everything is an object, everything, even adding, is a message. Squeak uses polymorphism, which means that the same message could do two completely different things, depending on what is receiving that message. To take an example from lecture, the “+” in “4 + 3” calls a different method from the “+” in “4.1 + 3.1.” In the first case, a small integer is receiving the message. In the second case, the java equivalent of a float is receiving the message. Each calls its own “+” method.

Squeak uses late binding. So, the receiver for the message is decided during runtime. If I were to have a temporary variable and in one case designate it as an integer and in the other designate it as a float, squeak would determine which one to send it to during execution. Also, if I were to have a class and a parent class with the same method, squeak would decide which one to use as well.

The standard set up for most squeak code is as such:

So in the earlier example, “4” would be the receiver object, “+” would be the message, and “3” would be the argument. Since everything is an object in squeak, even messages and blocks are objects. The object version of a method is designated with a “#”. So the object version of the factorial message would be “#factorial.”

One last thing to consider is the order of message execution: Parenthesis, Unary, Binary, and Keyword. This is in a first-come, first-served order. So squeak would evaluate anything in parenthesis, then any unary operators (like “factorial”), then any binary operators (like “+”), then any keyword operators (like “to:”). For example, the block “5 + 3 * 4 to: 100 + 600 do:” would evaluate “5 + 3” then “15 * 4” then “100 + 600” then “to:” then “do:”.

One of the advantages of method passing is that it is uniform. Since everything, even the most basic operations are messages, the format for everything is the same. If you are ever confused about how a message will execute, you can simply go to the receiver object class and look it up. Furthermore, it is easy to send blocks as arguments. There is no need to casting because squeak will decide the receiver at run time.

The downside of this is that it makes squeak prone to errors. If you create a class and send it a message that doesn’t exist, you won’t realize it until runtime. Also, for programmers not used to squeak’s style, the order of evaluation may be confusing and rather counter-intuitive.

Writing Code (1 point)
fib: anInt
"Returns the nth Fibonacci number"

(anInt = 0) 
	ifTrue: [^1].
(anInt = 1) 
	ifTrue: [^1]. 
        "These checks must be performed first, in case the number sent is 0 or 1"
(anInt < 0 | anInt isInteger)
	ifTrue: [self error: ['Must be a non-negative integer']].
        "Throw error if number is less than zero or not an integer"
(anInt > 1) 
	ifTrue: [^(self fib: (anInt - 2) + self fib: (anInt - 1))].

CoWeb Assignment #2
“The Debugger is Your Friend

The debugger is possibly one of the greatest tools in squeak. It allows you to see so much about your running code that you are almost immediately able to get to the root of the problem. A typical error message looks like this:

Uploaded Image: part1.JPG

At the top is a basic explanation of the error. In this case, we are trying to index a non-existent element in an ordered collection. While this message is pretty clear, in some cases it may not be, especially for beginning squeak users. You are given three options, proceed, abandon, and debug. Let us choose debug by clicking on the button. Now we should see a window that looks something like this:

Uploaded Image: part2.JPG

I have enlarged it a little for ease of viewing. Basically, in the top window, you see the stack of errors. The error usually occurs in the longer line with the brackets at the begging. I’ve circled it in blue. The lines below it are message calls leading up to the error. Let us click on the circled line.

Uploaded Image: part3.JPG

Once I click on a line, much more is revealed. The involved code is shown in the second box and the error causing message is highlighted in green. The bottom panels show the context of the errors. In this case, you can access all instance variables on the running class and in the right panels you can access all temp variables in the running method. It helps you see if anything is null when it shouldn’t be or perhaps when a value is wrong. Another great tool in squeak is the “Inspect It” option. You can reach it by highlighting an object you want to inspect (in this case to see what “animation scene” returns) and right clicking and selecting “inspect it” or just using alt-i.

Uploaded Image: part4.JPG

In this case, I get an error, the same error. This must mean that there is something wrong with my animation scene message. If I look at the stack and see what is happening in scene I will realize that animation is trying to access its scenes ordered list at a certain location but there is nothing there.

Uploaded Image: part5.JPG

In the bottom left, I can see that my currentIndex is 0. Since ordered list indexes begin at 1, this is a problem. Also, if I inspect scenes I realize that it has no values inside it. In this case, I realize that my error was caused by trying to add my character to the current scene before I created a scene. It would probably be prudent to add some error handling for that in the future.
To sum things up, the debugger is a great tool to track down your errors. From it, you can look into every instance and temporary variable and track down just where your error occurred. The bottom panels and the inspector are great aids in doing this.

Questionnaires (1 Point)

Prestige Bias
The user answers based on what they think would make them look good. “I work out everyday,” or “I always do the right thing.” It is a problem because it reduces the reliability of your questionnaire. If someone answers what they think they should say as opposed to what they think, then they are not giving you an accurate response.

The way to correct this is to make all the answers seem equal and normal. Do not lead into a question in a way that will produce bias towards one question or the other. Try to avoid questions that will produce responses like this entirely. Another method is to include a Lie Scale. It is a set of questions that have little to do with what you want to know but help give you insight into how likely a user is to pick socially desirable answers. The problem is that it bulks up the questionnaire and is usually not used in HCI.

Vague Questions
If you ask vague questions, you are likely to get vague answers or answers that don’t provide the information you want. Very open ended questions like “Do you like computers” aren’t going to give you much.

The way to fix this is to ask specific questions. Use questions like “Do you own a computer?” or “Could you find this feature within twenty seconds.”

Hypothetical Questions
Hypothetical questions ask about what a user might do in a certain circumstance. Since the user has never actually been in that circumstance, his or her answers might not be very accurate. For example, “If we changed this input from a text-based area to a radio button, would it be easier to use?” First, since the user has already had experience with the system, it ruins the novice user principle. Second, the user can only imagine if it would or would not, which is not accurate.

To fix it, use questions based from the users experience. Ask them specifically about the system they used, how easily they found each one of the features, etc. If you wish to make a change, you can ask the users’ opinions but keep in mind that it might vary from the actual result. Therefore, another set of tests and another questionnaire might be necessary after feature implementation.

Garbage Collection (3 Points)
A) Garbage collection has many advantages. The first is that it saves the programmer time because (s)he does not have to manually program it in. Secondly, it reduces programmer error (in the form of hanging pointers or memory leaks) because freeing memory is handled by the computer. With proper optimization, it can be reasonably fast as well.

On the downside, garbage collection is usually slower than manual freeing. It requires the processor to halt execution on a particular process to garbage collect, which may take several tenths of a second (too long if it happens in the processor of a guided missile). Secondly, it takes control away from the programmer, who might wish to free up memory at a certain time.

B) Reference counting is fairly simple. Each object has a reference counter, which is the number of pointers it has pointing to it. For example if I have an object Fish, and I have a variable pointing to it called aFish and another variable in a fish array at index 12, then it’s reference counter would be 2. If I removed both of these, it would be 0 and the garbage collector would finalize and remove it. The disadvantage of this is looping references. For example, in two-directional linked list, if one link points to another link and that link points back to the first, but nothing else points to either of them, they each have a reference count of 1. They will not be deleted even though they aren’t being used.

C) Mark and sweep starts from some root objects and determines everything that they are pointing to and everything that those pointed to objects are pointing to, etc. To better explain, look at the example below.

Uploaded Image: template.JPG
Here we have one root object and a bunch of other objects connected by references. The garbage collector starts by marking the root object (in gray).

Uploaded Image: step2.JPG
It then checks the all of the root object’s references and marks them gray, marking the root object black.

Uploaded Image: step3.JPG
It then checks all of the gray object’s references and marks them gray, marking the just-checked gray objects black.

Uploaded Image: step4.JPG
It repeats this process until all objects are black or white. The white objects are “swept” away, leaving only those with references behind.

D) Generational Scavenging works off the theory that the older an object is, the less likely it is to have no references pointing to it. As objects age, they move through the stages of eden, survivor, old, and tenured. This is not necessarily the exact process but it is similar. When garbage collecting, the garbage collector regularly checks eden and sometimes survivor, but rarely old or tenured. This helps to correct performance issues in two ways. One, since it checks much less space, it performs it in much less time. Two, since newer objects take advantage of the principle of locality of reference, it is more likely to remove objects that produce a cache hit as opposed to a costly miss.

In Stop and Copy, the heap is divided into two regions. Memory is only allocated in one region at a time. Once it runs out of space, garbage collection is performed. As each item is found to have a reference, it is copied compactly onto the other side. Forwarding pointers are left to their new locations. This solves the problem of memory fragmentation that garbage collection often produces over time. Since garbage collection and memory reallocation is done at the same time it always uses the half-space very efficiently. Unfortunately, this also means that you can only use half your heap at one time…

Links to this Page