In this article we're going to describe a tool that we've created to help OO newcomers understand the class/instance relationship, inheritance between classes and linking between objects...by automatically converting an object graph into HTML. The tool we've created is based on the "circlegram" idea used by almost every object-oriented teacher during conventional "chalk and blackboard" lessons.
Our work at the computer science department of Milano-Bicocca University in Italy is a mix of software design, programming and teaching. We use Unified Modeling Language (UML) for design, Java for programming and blackboards for teaching. When we teach, we also sometimes use overheads/slides. "So what?" you may say, "every teacher in the world does the same...."
Right, but we have an added problem: we have to teach Java and general OO (object-oriented) concepts to students at their very first course at the very start of their computer science career. So these students are often a complete tabula rasa they've had no prior programming experience whatsoever.
This happens because in Italy we don't have screening or filtering at entrance: every high school student can enter almost any university, and major in whatever he or she likes. There are no formal restrictions or requirements, so a student from a high school where they specialize in Greek and Latin can enroll to study software engineering or physics. (Students can then abandon or change studies as and when they realize their mistake, along the lines of the DOR army mechanism "Dismissed On Request".)
Given this situation, you can just imagine how our Java programming course attracts an eclectic group of students: we have students with no prior experience in using a PC, let alone programming!
The business world isn't that different. We dare say this because we also teach short Java courses for programmers from a wide variety of companies. They often have prior experience in languages such as COBOL, RPG, C, Visual Basic, and so on. Sometimes (very rarely) we also meet a C++ programmer. But prior knowledge isn't always an advantage: it can be misleading when you try to map a procedural language into an object-oriented one.
In both cases (university and business), we face a major problem when teaching Java and OO concepts: we call it the "class/instance problem." Newcomers and experienced procedural programmers alike find it difficult to fully grasp the meaning and the difference between a class and its instances (except of course in the case of a good C++ programmer).
Now of course we haven't discovered anything that wasn't already known; it's a problem that's been addressed before see for example Top-Down Teaching: Object-Oriented Programming in CSI by R. Decker and S. Hirsfield (ACM SIGCSE 1993, pp. 270-73). Indeed it's one of the reasons people debate whether or not choosing an OO language as the first language is the right thing to do.
Nonetheless, the class/instance problem remains the first and probably the biggest hurdle you face when teaching (and, seen from the student's point of view, when learning) your first OO language. We've seen students struggle with "can't make static reference to a nonstatic attribute" errors. We've seen Java programs with classes full of static methods and no instantiation at all. And we've seen many techniques described in the famous "How to write unmaintainable code" Web site (http://mindprod.com/unmain.html) actually being used!
Alas, the class/instance problem isn't the only one. When you code in Java you're forced to divide your product into many files. This policy is good for experienced programmers they can organize code better, in separate files and directories. But while the experienced programmer can keep track of the whole product, the Java newcomer isn't always able to see a bunch of classes as a complete program. When novices are editing a piece of code they have to remember every relationship existing between the current Java file and every other one. They must learn (and, we might add, learn very fast) that the class they're creating has attributes and methods not present in the current opened file. And we must help them as best we can.
To do so (and to help ourselves in teaching), we tried to address these problems by "porting" a teaching technique taken from traditional classroom lessons to a software tool.
What We Needed, What We Produced
We started from something we knew very well: classic "chalk and blackboard" teaching. During traditional lessons, when we need to explain the class concept and the instantiation mechanism, we usually try to explain the coupling between class and instance by speaking and drawing on the blackboard. We use phrases like "any class you define is a template...," "when you instantiate an object you're in fact allocating memory...," "attributes are allocated at their respective class level...," and other more metaphorical ones that we won't bother to report here. To represent a runtime situation, we usually draw "circlegrams" on the blackboard (see Figure 1).
The example shown in Figure 1 is a common form of circlegram: it represents an instance of a hypothetical class C with its attributes, both native and inherited, correctly placed (every attribute has an example value).
To mimic the classroom situation we created a package, called HTMLStream, to generate an HTML representation of a circlegram. Remember that we want to map inheritance with a circlegram, but we also want to show the linking between objects (reference attributes). In HTML there are hyperlinks a perfect solution for mapping object links. So we had to create only the inheritance representation. We chose the HTML TABLE to represent an object instance, with a recursive table-in-table to show inherited attributes. The current format is shown in Table 1.
This representation should also be familiar to someone accustomed to UML class symbols, except that in our case inherited attributes are embedded inside the object instead of having an arrow pointing to the extended class. The table-in-table format converts an object like the one shown in Figure 2 into the HTML visualization shown in Figure 3.
When converting a complex object graph, our tool will generate an HTML page (it may be a long page) with links and internal anchors. An object graph (a bunch of interlinked instances in memory) is "linearized" in one single HTML page. Every reference between instances is mapped with an internal link to an anchor on the same page; in fact, every single object is converted into a piece of HTML text that contains links to other "objects," and is also a target (HTML anchor) to be pointed to. Graphically, every object having reference attributes will look like the one shown in Figure 4.
At runtime, in memory, the same object will be allocated as a graph (see Figure 5).
Our generator will create an HTML page similar to the one rendered in Figure 6.
The HTMLStream tool can be used during a lesson to explain inheritance and reference attributes, but of course it can also (and should also) be used by all students to experiment with their own source code. Students feel at home browsing an HTML page; they'll explore objects the same way they explore the Internet.
The whole process of generating an HTML page from instances in memory can be described with this checklist:
- Design time: Describe your classes using UML - or other formal design languages (see Figure 7).
- Coding time: Write your Java source code, adding special printing instruction (see "How to Use HTMLStream" section later in the article). Below is the example source for class MyClass (methods removed) that has been converted and shown in Figure 6:
public class MyClass
- Runtime: Run the code redirecting output to a file
- Browsing time: Examine the result again see Figure 6.
Other Products Already Available
Of course, before developing this product we searched the Internet to see if there were any similar tools already in existence. We found there are two main categories of software visualization: source visualization and runtime visualization.
Source visualization is used by developers to keep track of what they (or other developers) have done. With source visualizers, you can produce, for example, call graphs, statistical reports and tree representations. Runtime visualization is subcategorized into pre- and postmortem visualization, "pre" meaning "running" and "post" meaning "after completion."
Information about software visualization is readily available starting at www.cc.gtech.edu (the research area of professor Stasko and colleagues). There's also a journal article to be aware of, "An Effective Web-based Software Visualization Learning Environment" by J. Domingue and P. Mulholland, in the Journal of Visual Languages and Computing, 9 (5), 1998, pp. 485-508. And there's a book chapter too, "Using Software to Teach Computer Programming: Past, Present and Future" by P. Mulholland and M. Eisenstadt, in Software Visualization: Programming as a Multimedia Experience (Cambridge, MA: MIT Press, 1998).
In its present version, HTMLStream is mainly a postmortem visualizer, even though it produces output throughout the execution of the analyzed program. At the end of execution, the user can browse through the HTML page and view what's just happened.
After our resource search we decided not to use any of the preexisting tools for the following reasons:
- Most of the products already created are targeted at runtime visualization, that is, they generally don't save any state for later viewing (apart from "core dumps").
- Very few of them are developed for the Java language.
- Most of the ones already usable for Java weren't free.
The most relevant candidate among those that were free, BlueJ (BlueJ - Teaching-Oriented Java IDE - see www.sd.monash.edu.au/bluej) is an interesting product developed for teaching OO that has an object inspector but doesn't show attribute inheritance. (BlueJ is also an IDE, whereas for teaching purposes we needed nothing more than the standard JDK. We didn't want to confuse students with a GUI product; we believe they must learn the language by writing code character by character.)
How to Use HTMLStream
First, here's a four-step checklist for the impatient:
Next, instructions for everyone else. When you need to "print" (convert to HTML) an object you must:
- Download the package available from the HTMLStream home page (www.sal.disco.unimib.it/~atrent/htmlstream.htm).
- Compile everything ("javac *.java").
- Run MyClass ("java MyClass" or "java MyClass > file.html" if you want to capture output in a file for later viewing).
- Watch the screen, and you will be shown a JFrame containing an example HTML-ization (see Figure 8).
This means that you can use HTMLStream only by inserting special printing statements in your code. Another thing to bear in mind is that not every object is "printable": you can print only certain types of objects, namely the ones that implement the HtmlizableI interface. Let's see our first example:
- Create an instance from the HtmlStream class.
- Pass the reference of the printable object to the HTMLStream.
- "Print" the HTMLStream object, in the usual Java way (System.out.println).
// MUST be HtmlizableI
MyClass toBePrinted = new MyClass();
// "the printer"
HtmlStream hStream = new HtmlStream(toBePrinted);
// print the HTML representation
The HTMLStream is also useful if you want to add (or "queue") other objects at a later time - assuming that we still have hStream in scope:
// adding new objects
/* print the HTML representation,
this time includes the new objects */
This last example is one reason for the existence of the HTMLStream class: it's useful when you need to queue more than one reference for printing. It's very similar in usage to the ObjectOutputStream; in fact, the HTMLStream works more or less the same way (i.e., conceptually). A mental aid when using HTMLStream is the "printing queue" metaphor: you submit objects to the stream when you're satisfied you can start the actual printing of the stream itself.
How Can I Make My Objects Printable?
As we mentioned before, an object must be HTML-printable to be passed to the HTMLStream. To make an object fulfill this criterion you have two basic choices:
A problem that affects this implementation (and will probably be circumvented in future releases) is that standard JDK objects are not already HTML-printable. To print a standard JDK object you either have to build a wrapper class that translates it into an HtmlizableI object, or you must "explode" it if it's some kind of container. An example of the latter case can be found inside the DefaultHtmlizable class source: we explode a Vector or a Hashtable; look at the method isComplexUsable(Object o) in the file DefaultHtmlizable.java.
- Your object implements the HtmlizableI interface. This way (and it's the hard one), you must implement every method in that interface, but at least you spare the Java single-inheritance for something else.
- Your object inherits from DefaultHtmlizable class (provided in the package). This way, you don't need to implement anything; you just extend a particular class and that's it: your object inherits HTML printability. By contrast, you can't inherit anything else (at least in Java).
How We Did It Implementation Notes
(Authors' Disclaimer: Please note that we designed this tool for teaching purposes only, so our implementation is somewhat "quick and dirty" and can certainly be improved upon.)
To implement this htmlization mechanism, we took inspiration from the serialization feature already present in Java. This "pattern" is very similar to the Externalizable mechanism: the serializable object must "do something" to be serialized; it's not completely passive.
Remember that we had to render the three aspects mentioned above: inheritance, attributes and links (references to other objects). Inheritance is represented by the recursive table-in-table (every attribute is printed coupled with its value). Any link (attribute that is a reference) will be a hyperlink to an anchor somewhere on the same page.
The main problem in performing this conversion is, for example, when an object points to another object, which in turn points to another one, which in turn points to the first one that is to say, a circular list. This is a common situation in a running program. In fact, we call them object "graphs," not trees. If we want to convert everything automatically, meaning that every reference inside the root object (initial object) is automatically followed, we need a way to avoid infinite loops when converting circular graphs or even the simple multiple referentiation.
Loop avoidance is the primary rationale for the existence of the HTMLStream class. An HTMLStream is a "container" that can be "grown" by adding HtmlizableI objects. An "add" operation wonÕt succeed if an object is already present in the stream.
We must solve another problem: automatic reference following. If we want to "print" an object through this stream, we want to avoid passing every single reference to be printed; we just want to pass the graph "root" (quoted since it is a graph and there is no formal root) and let the stream do the rest. This is the role of any HtmlizableI object (implemented in the DefaultHtmlizable class): instances from this class can scan their attributes and treat them "correctly," automatically adding to the stream every referenced object (have a look at the method grow() in DefaultHtmlizable.java). The pseudocode for the scan&grow algorithm is:
for every attribute of this instance
if attribute is NOT primitive
if attribute is HtmlizableI
wrap it (if possible) and grow stream
Actually, this procedure is executed at each class "level." We use reflection to extract attribute details, and we do this for each class level up to but excluding Object, the top class in Java. For every class level scanned we open a new TABLE tag. At the end we close everything, thus drawing our desired "html circlegram."
Ideas for Past, Present and Future Development
Last year, at the beginning of our work, we thought about using XML for conversion and viewing (see www.xml.org , www.xml.com and www.w3.org). Back then, we abandoned the idea because of the prevailing lack of XML tools, but the situation is evolving rapidly. Since it's now gaining respect, even in the Java world, XML could be a viable option now.
There are two categories of ideas for development: minor (e.g., aesthetic or "easy" to implement) and major (e.g., semantic) improvements.
Minor ones could be:
- Adding access indicators: Add public, private and protected access indicators to the attributes printed.
- Resetting the stream: If you need to add a previously added object to the stream you can't; at present you must reinstantiate the HtmlStream. We need a method similar to the ObjectOutputStream.reset().
- Adding a "link count" feature to the HtmlStream: Incrementing a counter instead of simply discarding an object already present in the stream). This feature could roughly evaluate the "spaghettization" level of a student's code.
As for major improvements, there are only two:
- Generating a Web site: Instead of generating a single text stream, it would be useful to generate a Web site: every instance could be represented as a single page with links to other pages instead of internal links (anchors). This way you could graph your site with existing tools (FrontPage, for example, generates a graphical map of a site). The graph would represent a visual glimpse of your runtime situation and you could also navigate every printed instance with the omnipresent Web browser! To implement this new format we need to rearrange the classes a little bit (e.g., an object must present itself in at least two HTML forms: the single-page mode and the sitemode). In sitemode every page should be named after the object itself; in Java this could be based on the toString() form of an object something like [email protected] (<classname>@<hashcode>.html).
- Adding a historicization mechanism: The object htmlization as seen here is a somewhat static mechanism: at some point in code you print an object, overwriting the previous state. A historicization mechanism would be very useful, but it would have to be carefully planned. To be honest, it's probably a major change in source code. Also, great care must be taken in designing the htmlization: how an object state change could be rendered in html. We need an effective way of simultaneously representing objects, links and their modification in time.
- The current mechanism (extending the DefaultHtmlizable class or implementing "ex novo" a HtmlizableI object) is good enough for teaching purposes. But in real-world applications it would be better if an object could be printed anyway simply by encapsulating it into another object. In Java you can do this by using the serialization protocol and converting a serialized stream in an HTMLStream. This way, the only constraint (at least in Java) is that your printable object must also be declared java.io.Serializable (an interface this way you don't miss inheritance with other classes). Implementing a serialization wrapper needs more work than for the simple "extends DefaultHtmlizable" solution.
- Using VRML as output format would also be very interesting, but we don't have the resources at the moment to experiment in the VRML field.
Is HTMLStream good for teaching? Is HTMLStream good for first-year students without programming experience? We believe that, yes, this tool is good for teaching: we've used it in some short courses (on students with some prior programming experience) and it greatly helped us with "bootstrapping" people. But we still have to test it on students as their first-ever experience.
A tool like HTMLStream and not only HTMLStream, but any tool must be introduced with care. Novice users need to be introduced first to general programming principles, then to the joys of editing we had students editing source files who didn't know where they'd saved them! and to the problems associated with using a PC (for example, if they're very young they often ignore basic concepts such as command prompt and redirection). We'd be very happy to receive some feedback from JDJ readers. The complete source code for this article can be downloaded from the JDJ Web site, JavaDevelopersJournal.com.
Both Daniela Micucci and Andrea Trentini have worked since 1997 as researchers at Dipartimento di
Informatica, Sistemistica e Comunicazione (DISCo), the Computer Science Department of MilanoBicocca University in Italy. Since receiving their computer science degrees, they've both been teaching Java and OO design to companies, in schools and at the university level.
Andrea's research field involves studying and designing software architectures for educational management; contact her at: [email protected].
Daniela's involves designing traffic control and monitoring software.
She can be contacted at: [email protected].