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

Conroy Whitney

Personal

Some Abouts:
Status: 2nd year (4th semester) CS Major; Co-op at CareerBuilder.com
Interests: Software Architecture and Web Design
Valued Experience: VB/ASP.NET, PHP5, MySQL, the rest of the web-jargon acronyms

Contact Info:
Email: gtg850w at the usual
AIM: IN312T

Current Classes, Summer '06:

Team Info

Team Objects are Nouns

Assigments

On Method Overloading vs. Dynamic Dispatch... (CoWeb Assignment 3, pt. 1)

In a statically-typed language, there exists a concept of Method Overloading [en.wikipedia.org] wherein two functions of the same name can be declared with different signatures. The correct function. is chosen and invoked at compile time depending on the incoming parameter types. For example, consider the following two functions in Java that recieve two numbers and return their added result:


public class MyObject {
    ...

    public int add(int a, int b) {
        System.out.println("Adding two ints.");
        return a + b;
    }

    public int add(float a, float b) {
        System.out.println("Adding two floats.");
        return a + b;
    }

    ...
}

In this example, when myObject.add(a, b) is called the specific recieving function is determined by the types of a and b.

Dynamic Dispatch [en.wikipedia.org] is a concept by which a correct method or message-handler is found is found during runtime based on the type of the object being sent the message. In the following Squeak script, the even message-handlers in Number, Integer, and SmallInteger have been augmented to print out their respective Class-Names:


    4 even
    (SmallInteger) true

    4.0 even
    (Number) true

    10000000000 even
    (Integer) true  

Since Squeak uses dynamic dispatch, the message even is handled at runtime. The type of the recieving object is evaluated and the correct message-handler is found for the message based on this object's type. This results in the SmallInteger 4 handling the message in its own class instead of its parent's (Integer's), whereas the Float 4 must use its parent's (Number's) handler.

Multiple Dispatch is a concept that combines both Dynamic Dispatch and Method Overloading. The correct message-handler is determined by both the object-type of the recieving object and by the object-types of the parameters.

On Closures... (CoWeb Assignment 3, pt. 2)

  • What are Closures?
  • Why Closures are important in Object-Oriented Programming
  • Example of a Closure in Squeak

Closures [en.wikipedia.org] are essentially bits of program-logic encapsulated with all the data (specifically, variable references) they need to perform said logic. The code is bundled with all the variables for its own block as well as any references to variables outside of its block that it needs. In object-oriented programming, closures provide a way of encapsulating a sequence of logic into a First-class Object that can be passed around like any other variable. For example, the following code is an example of an if/else statement in Squeak that utilizes closures:


    myTest := true.
    (myTest = true) ifTrue: [
        Transcript show: 'myTest was true, see? myTest: ', myTest asString.
    ] ifFalse: [
        Transcript show: 'myTest was false, see? myTest: ', myTest asString.
    ].

In the above example, the resulting boolean of the test (myTest = true) is sent two blocks of code as messages to its ifTrue:ifFalse: message-handler. It then executes one of the chunks of code depending on its value. It is important to note that a block of code is only evaluated when executed which means that some blocks will never be evaluated at all. Also, realize that the chosen code block is executed by the Boolean and not in the same scope where the two blocks were originally defined. This is an example of how both code and variable-references are encapsulated into closures.

On Garbage Collection... (CoWeb Assignment 3, pt. 3)

  • When can the Reference Counting algorithm become problematic?
  • Advantages and disadvantages to using garbage collection

Garbage Collection [en.wikipedia.org] is the automated process of sifting through memory during runtime and deciding which areas of the heap can be regained. This is usally performed by the virtual machine when it decides (or is told) that it would be beneficial to clean up memory. There are a handfull of different algorithms for deciding which areas of memory can be reclaimed. Reference Counting [en.wikipedia.org] is such an algorithm that involves keeping a count of how many references to an object exist. When an object no longer has any references, it is deemed safe to clean up that chunk of memory. A problem arises, however, when two objects point to each other: even there are no 'external' references to either of those two objects, each will supply the other with the one reference needed to remain un-collected.

For some programming languages such as Java and C#, garbage collection is an integral part of their structure and performance. Using such languages can provide a programmer with two main benefits: safety and ease-of-use. Since all of the memory allocation/deallocation is left up to the language, the programmer is freed from the responsibilities and quirks that come from memory management. Additionally, garbage collection languages provide a safety net against memory overflow and ensure that, when it becomes necessary, the program is as compact as possible to maximize memory usage.

It is important to note, however, that the benefits of garbage collection come at a price. Although algorithms can differ between how much of the memory is cleaned and how often, each unfailingly requires additional computing time. Before programming with a garbage collection language, it is important to decide if the additional computation time is both available and worth the benefits mentioned above.

On Refactoring... (CoWeb Assignment 2, pt. 1)

  • What is refactoring?
  • Why should you do it?
  • How do you know when to refactor?
  • How should you go about refactoring?
  • How can unit testing be useful when refactoring?

Refactoring [en.wikipedia.org] is the process of re-designing and optimizing code without changing its functionality. After a refactoring iteration, code should be more readable, more efficient, and more extensible [en.wikipedia.org]. Although cost is traditionally an argument against refactoring ("What do you mean you're going to code for a week and we don't get any new features?"), in general refactoring will result in a better coding environment for you the programmer which, in turn, increases your efficiency.

Although refactoring becomes more necessary as a project becomes larger, many small projects will never need to be refactored on a large scale; however, these are some common ailments in any system that beg refactoring:

  1. Problem: You are copy-pasting code and, as a result, must re-copy-paste upon any changes.
    Refactored: Create a reusable method to handle that functionality. This eliminates duplication.

  2. Problem: You are performing multiple ifs or switches on objects and their properties.
    Refactored: Move that logic into the objects themselves, particularly using polymorphism.

  3. Problem: You have very long methods that are hard to read through and follow.
    Refactored: Extract some of that logic into one or more reusable methods. This will help with readability as well as minimizing duplication.

  4. Problem: You find your objects are nonsensical with their method or attribute ownerships.
    Refactored: Think about what concept the object is intended to represent and decide if that concept should own those methods or attributes or if perhaps one or more additional objects are needed.

  5. Problem: Your program's functionality domain has extended.
    Refactored: Think about the new domain before you start hacking code. Does your current architecture make sense in this new domain or will you need to extend your architecture along with your domain?
If you find your code victim to any of the bad practices listed above, you could probably use some refactoring. Check out the Wikipedia Refactoring Page [en.wikipedia.org] to see some common refactoring techniques.

Once you know what you need to refactor, you must decide how you will go about refactoring. Essentially this is project-specific but, generally, it is best to start with an iteration that will give you the biggest benefit (i.e., the most useful change).

Testing is important througout the refactoring process. If you do not test aspects of your project consistently, you will most likely end up with a broken system. It is very similar to writing a large program and not running it until the very end: you end up with hard-to-track bugs; however, if you refactor in smaller iterations and test your system after each iteration, you can catch and repair bugs more efficiently. To this end, any sort of Unit Test [en.wikipedia.org] can be useful in assuring you that your refactoring process is not destroying the system.

On Inheritance... (CoWeb Assignment 2, pt. 2)

  • What is the difference between class-based and prototype-based inheritance?
  • What properties get inherited?
  • What is one advantage of prototype-based inheritance?
  • What is one advantage of class-based inheritance?

In class-based inheritance, objects are created to represent the "concept" of that class. For instance, if you have an Car class (which would have properties such as "tires", "engine", "steering wheel", and "doors"), you could create a Car object which would have those said properties. If, perhaps, you wanted to distinguish between a 2-door coupe and a 4-door sedan, you would create two subclasses Coupe and Sedan which would override the "doors" property to distinguish between their 2 and 4 doors, respectively. Thus, a Coupe object would have 2 doors, and a Sedan object would have 4 doors.

In prototype-based inheritance, objects are created from a "prototype" -- i.e., they are based off an existing object and just extended or modified as necessary. For instance, you could have a Car object (which would have the same properties as above) but, in this case the Car object can by default have 4 doors (since most do, right?). Now, if you wanted to create a Coupe object, you would simply clone the Car object and change its number of doors to 2, since a Coupe is essentially a car with 2 doors.

Prototype-based inheritance can provide a simpler, more logical form of inheritance. A car is a car whether it is a two-door coupe or a four-door sedan; however, with class-based inheritance, there is more control over what gets inherited and how certain classes are different from each other. A coupe is a car, but it has 2 doors; a sedan is a car, but it has 4 doors.

Inheritance differs between the two paradigms as follows: with class-based inheritance, only properties with the correct scope (i.e., public or protected in Java) will be passed on to an inherited class. This allows for more control on which classes will be able to modify which properties. With prototype-based inheritance, all properties of the original object are passed on to the new object.

For more information, check out the Prototype-based Object-oriented Programming section on Michael Traver's Programming with Agents page.

Useful Cases From Previous Semesters (CoWeb Assignment 1)

  1. Mini Java-to-Squeak Tutorial
    This case gives a brief comparison between commonly used programming tools (such as defining variables and loops) in both Java and Squeak. I found this useful not only as a reference but because of the way they decided to format their code. They explicitly show a connection between {}s in Java and []s in Squeak. Combined with what we have learned thus far in class, I believe that this page brings me to a more full understanding of how to program in Squeak.

  2. Video Professor: Because reading is HARD.
    This case is a series of videos (hosted by youtube.com) that demonstrate some useful features of programming Squeak in Morphic. These videos quickly and memorably demonstrate how to perform from the most basic to the most useful actions in Morphic which, I feel, saves alot of time in getting to know the GUI. Since so much effort can be wasted on trying to find something something simple when using a new programming environment, I believe these videos (which, when you think about it, ARE much easier than reading) are a must-view when beginning in Morphic.

  3. General useful Squeak stuff
    This is another useful reference page that mostly covers how to do reflective and conversion processes in Squeak. Since this page shows actual squeak code, it yet another opportunity to learn how to program in Squeak. If you play around with these code samples in Morphic, you can experience important examples like inheritance the Squeak way.

  4. Group No. 9
    This case sums up what we were supposed to have learned from 2335 but no doubt will forget when we start forming groups and coding our semester project. It is a list of important reminders about the importance of design, how to code as a group and, specifically, how to code in Squeak so that others will be able to understand your code later. These points are worthwhile for any group coding project and are a must-read for this class -- if not only for a reminder of what we would have told ourselves after the end of a class like 2335.



Links to this Page