old-www/LDP/LG/issue62/steffler.html

403 lines
22 KiB
HTML

<!--startcut ==============================================-->
<!-- *** BEGIN HTML header *** -->
<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 3.2//EN">
<HTML><HEAD>
<title>Making Smalltalk: The Making of aPerson LG #62</title>
</HEAD>
<BODY BGCOLOR="#FFFFFF" TEXT="#000000" LINK="#0000FF" VLINK="#0000AF"
ALINK="#FF0000">
<!-- *** END HTML header *** -->
<CENTER>
<A HREF="http://www.linuxgazette.com/">
<H1><IMG ALT="LINUX GAZETTE" SRC="../gx/lglogo.jpg"
WIDTH="600" HEIGHT="124" border="0"></H1></A>
<!-- *** BEGIN navbar *** -->
<IMG ALT="" SRC="../gx/navbar/left.jpg" WIDTH="14" HEIGHT="45" BORDER="0" ALIGN="bottom"><A HREF="silva.html"><IMG ALT="[ Prev ]" SRC="../gx/navbar/prev.jpg" WIDTH="16" HEIGHT="45" BORDER="0" ALIGN="bottom"></A><A HREF="index.html"><IMG ALT="[ Table of Contents ]" SRC="../gx/navbar/toc.jpg" WIDTH="220" HEIGHT="45" BORDER="0" ALIGN="bottom" ></A><A HREF="../index.html"><IMG ALT="[ Front Page ]" SRC="../gx/navbar/frontpage.jpg" WIDTH="137" HEIGHT="45" BORDER="0" ALIGN="bottom"></A><A HREF="http://www.linuxgazette.com/cgi-bin/talkback/all.py?site=LG&article=http://www.linuxgazette.com/issue62/steffler.html"><IMG ALT="[ Talkback ]" SRC="../gx/navbar/talkback.jpg" WIDTH="121" HEIGHT="45" BORDER="0" ALIGN="bottom" ></A><A HREF="../faq/index.html"><IMG ALT="[ FAQ ]" SRC="./../gx/navbar/faq.jpg"WIDTH="62" HEIGHT="45" BORDER="0" ALIGN="bottom"></A><A HREF="lg_backpage62.html"><IMG ALT="[ Next ]" SRC="../gx/navbar/next.jpg" WIDTH="15" HEIGHT="45" BORDER="0" ALIGN="bottom" ></A><IMG ALT="" SRC="../gx/navbar/right.jpg" WIDTH="15" HEIGHT="45" ALIGN="bottom">
<!-- *** END navbar *** -->
<P>
</CENTER>
<!--endcut ============================================================-->
<H4 ALIGN="center">
"Linux Gazette...<I>making Linux just a little more fun!</I>"
</H4>
<P> <HR> <P>
<!--===================================================================-->
<center>
<H1><font color="maroon">Making Smalltalk: The Making of aPerson</font></H1>
<H4>By <a href="mailto:jagwar@magma.ca">Jason Steffler</a></H4>
</center>
<P> <HR> <P>
<!-- END header -->
<table COLS=2 WIDTH="100%" NOSAVE >
<tr NOSAVE>
<td NOSAVE>
<center>
<h1>
<img SRC="misc/steffler/makingSmalltalk.png" ></h1></center>
<center>
<h3>
The Making of aPerson</h3></center>
<p>&nbsp;
<br>&nbsp;
<br>&nbsp;
<center>
<p>By <a href="mailto:jagwar@magma.ca">Jason Steffler</a></center>
</td>
<td WIDTH="200" NOSAVE>
<center><img SRC="misc/steffler/penguinInBalloon.gif" height=230 width=200></center>
</td>
</tr>
</table>
<div align=right>
<hr WIDTH="100%"><b>Article #4 - Feb 2000</b></div>
<h2>
<a NAME="abstract"></a>Abstract</h2>
&nbsp;&nbsp;&nbsp; For those who haven't read the previous articles, be
sure to read <font size=+1><a href="http://www.linuxgazette.com/issue60/steffler.html#statementOfPurpose">the
statement of purpose</a></font> first.&nbsp; This month, we're going to
discuss the making of <b>aPerson
</b>- how to use browsers to do so and
some OO considerations.&nbsp; For those looking to read the whole series
locally or information about upcoming articles, you can
<font size=+1><a href="http://www.magma.ca/~jagwar/makingSmalltalkForwardingPage.html">check
the MST page</a></font>.&nbsp; For those looking for further information
on learning Squeak, here are <a href="http://minnow.cc.gatech.edu/squeak/377">some
good resources</a>.
<br>&nbsp;&nbsp;&nbsp; Something different this month is that I'm dropping
the local links usage (was [LL]), as they weren't being used as much as
I'd anticipated.
<h2>
<a NAME="quoteOfTheDay"></a>Quote of the day</h2>
"The main problem for the C++ community today is to use Standard C++ in
the way it was intended rather than as a glorified C or a poor man's Smalltalk."
<br>&nbsp;&nbsp; - Bjarne Stroustrup (inventor of C++), "Getting From The
Past To The Future" , p. 23 C++ Report, SIGS Nov/Dec 1999 Vol1 No.10
<h2>
The Making of aPerson</h2>
&nbsp;&nbsp;&nbsp; Before we get started this month, the code-along folks
will want to file in the next version of the <b><a href="MakingSmalltalk-Article4.st">ScopedBrowser</a></b>
that was introduced last month.&nbsp; If you saved your image with the
browser in it - don't worry about conflicts as this new filein will replace<sup><a href="#footnotes">1</a></sup>
the previous <b>ScopedBrowser </b>(<a href="http://www.linuxgazette.com/issue60/steffler.html#puttingItAllTogether">see
article 2 on how to file in</a>) This time around I've added a few more
classes to the scope; the classes that are used for making a <b>Person</b>
class, and also a few more classes for good measure:
<ul>
<li>
<b>Boolean</b> (the super class of True and False)</li>
<li>
<b>False</b></li>
<li>
<b>Object</b> - the base object of Smalltalk that all other objects are
subclassed from<sup><a href="#footnotes">2</a></sup></li>
<li>
<b>True</b></li>
<li>
<b>Workspace</b> - the class we will be using to open textual windows</li>
<li>
<b>ScopedBrowser</b> - in case you're curious about the browser that we're
using.&nbsp; If you want to fiddle around with this guy, be careful to
save your image first, as it's not too hard to mess something up that affects
the browser that you're using to mess around in.</li>
</ul>
&nbsp;&nbsp;&nbsp; On the above note, you can fiddle with anything you
wish in Smalltalk, including the <a href="#articleGlossary">base classes</a>.&nbsp;
Though you can (and sometimes need to) do base class changes, it's generally
not advised as it's very easy to mess up the image or to break forwards
compatibility.&nbsp; If time/space allows in a future article we'll talk
more about base class changes.&nbsp; For now just be aware to save your
image before doing base class changes, and if you decide to keep a base
class change, keep a backup of your image before the change.
<br>&nbsp;&nbsp;&nbsp; Now getting to coding the <b>Person</b> class, if
you filed in the
<b>Person</b> code from article 2, then you'll either
want to remove that class from your system, or code this example as <b>Person2</b>,
or <b>JrsPerson
</b>(prefix with your initials), or some such thing to
avoid <a href="#articleGlossary">namespace collisions</a>.
<br>&nbsp;&nbsp;&nbsp; I'm going to remove the <b>Person</b> class and
start fresh, if you decide to to do this route, then open the <b>ScopedBrowser</b>
by doing this code:
<p>&nbsp;&nbsp;&nbsp; <b>ScopedBrowser openBrowserForArticle4</b>
<p>&nbsp;&nbsp;&nbsp; You'll notice that there are seven categories available,
including <b>MakingSmalltalk-Article2</b>.&nbsp; If the Person class exists,
it should be in this category.&nbsp; <b>Left-click</b> on the <b>Person</b>
class, then <b>middle-click>Remove</b>.&nbsp; You'll get a confirmation
dialog, click <b>yes</b> in this.&nbsp; You'll see now that the category
<b>MakingSmalltalk-Article2</b>
is empty.
<br>&nbsp;&nbsp;&nbsp; Now, to first declare our <b>Person</b> class, in
the <b>ScopedBrowser</b>, left click on the <b>MakingSmalltalk-Article4</b>
category, you'll see the code pane displays a nice class template for you.&nbsp;
It's pretty straightforward:
<blockquote><b>Object subclass: #NameOfClass</b>
<br><b>instanceVariableNames: 'instVarName1 instVarName2'</b>
<br><b>classVariableNames: 'ClassVarName1 ClassVarName2'</b>
<br><b>poolDictionaries: ''</b>
<br><b>category: 'MakingSmalltalk-Article4'</b></blockquote>
&nbsp;&nbsp;&nbsp; Don't worry about what a pool dictionary or class variable
is, just edit this template such that it looks like:
<br><i>[ex1a]</i>
<blockquote><b>Object subclass: #Person</b>
<br><b>instanceVariableNames: ''</b>
<br><b>classVariableNames: ''</b>
<br><b>poolDictionaries: ''</b>
<br><b>category: 'MakingSmalltalk-Article4'</b></blockquote>
<b>&nbsp;&nbsp;&nbsp; </b>Then <b>middle-click>accept.</b>&nbsp; You'll
notice that the <b>Person</b> class has been added to the article 4 category.&nbsp;
Now lets add a method, the first method we discussed in article 2 was <b>sing.Right-click>new
category...>new...</b> in the method categories pane, and type in: <b>Singing</b>
as the method category name, then click on the <b>Accept</b> button.&nbsp;
You'll notice that the code pane gives you a nice method template:
<blockquote><b>message selector and argument names</b>
<br><b>&nbsp;"comment stating purpose of message"</b>
<p><b>&nbsp;| temporary variable names |</b>
<br><b>&nbsp;statements</b></blockquote>
&nbsp;&nbsp;&nbsp; Copy over this method template with our <b>sing</b>
method, then <b>right-click>accept</b>.
<br><i>[ex1b]</i>
<blockquote><b>sing</b>
<br><b>&nbsp;&nbsp;&nbsp; (Workspace new contents: 'Do be do be doooooo.')
openLabel: 'A bad impression of Sinatra'.</b></blockquote>
<b>&nbsp;&nbsp;&nbsp; </b>You'll notice that the <b>sing</b> method appears
in the method category <b>Singing</b>.&nbsp; You can now go to a workspace,
and do: <b>Person new sing</b>, and the bad impression will appear.&nbsp;
For the read-along folks, the browser looks like:
<br><img SRC="misc/steffler/ScopedBrowser1.png" height=283 width=469>
<p>&nbsp;&nbsp;&nbsp; Now the next method we discussed was <b>sing:, </b>and
it could take a parameter: <b>'MaryHadALittleLamb'</b>. You can see the
obvious difficulty with our first sing method - the song and label are
hard-coded along with the activity that we're doing.&nbsp; It'd make more
sense to have one method that knows the activity we're doing (singing),
and be able to have it accept parameters from various methods to simplify/reuse
our code.&nbsp; That way, if we need to change how the singing is done
in the future, there are less spots to update.&nbsp; Lets make a new method
(remember, we're denoting private methods with a 'my' prefix) that isolates
how we're doing the singing from what is being sang:
<br><i>[ex1c]</i>
<blockquote><b>mySing: someLyrics withTitle: aTitle</b>
<br><b>&nbsp;&nbsp;&nbsp; (Workspace new contents: someLyrics) openLabel:
aTitle</b></blockquote>
&nbsp;&nbsp;&nbsp; Then, lets <a href="#articleGlossary">refactor</a> our
first <b>sing</b> method to reuse this private method, just copy right
over the sing method or edit the text directly and accept it:
<br><i>[ex1d]</i>
<blockquote><b>sing</b>
<br><b>&nbsp;&nbsp;&nbsp; self mySing: 'Do be do be doooooo.' withTitle:
'A bad impression of Sinatra'</b></blockquote>
&nbsp;&nbsp;&nbsp; Note that we still have the song lyrics and title hard
coded in the <b>sing</b> public method, so they're not directly accessible
by other objects or methods of <b>Person, </b>but it is better than it
originally was.&nbsp; We'll show a better way to organize your code when
we do our next song, and illustrate how factoring out the song lyrics can
be useful.&nbsp; With this in mind, lets create a lyrics method for our
next song:
<br><i>[ex1e]</i>
<blockquote><b>maryHadALittleLambLyrics</b>
<br><b>&nbsp;&nbsp;&nbsp; ^'Mary had a little lamb, little lamb, little
lamb, Mary had a little lamb whose fleece was white as snow.'</b></blockquote>
&nbsp;&nbsp;&nbsp; Now we can add our <b>sing:</b> method that reuses our
private <b>mySing:withTitle:</b> method.&nbsp; It has some very simple
logic that defaults to our bad impression if we don't understand what is
being requested to sing.&nbsp; Note:&nbsp; when we ask <b>aSong </b>if
it's equal to <b>'MaryHadALittleLamb', </b>a boolean object is returned
(true or false), and then we ask the boolean object if it's true or if
it's false.
<br><i>[ex1f]</i>
<blockquote><b>sing: aSong</b>
<br><b>&nbsp;&nbsp;&nbsp; aSong = 'MaryHadALittleLamb'</b>
<br><b>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; ifTrue: [self mySing:
self maryHadALittleLambLyrics withTitle: 'Mary had a little lamb']</b>
<br><b>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; ifFalse: [self sing].</b></blockquote>
&nbsp;&nbsp;&nbsp;&nbsp; Remember, as soon as you add a method, you can
execute it if you like, since no compile-n-link-n-run cycle is needed.&nbsp;
Finally, lets add our last public singing method, which is similar to the
above method:
<br><i>[ex1g]</i>
<blockquote><b>sing: aSong andDoIt: anAdjective</b>
<br><b>&nbsp;&nbsp;&nbsp; aSong = 'MaryHadALittleLamb'</b>
<br><b>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; ifTrue: [self mySing:
self maryHadALittleLambLyrics inManner: anAdjective withTitle: 'Mary had
a little lamb']</b>
<br><b>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; ifFalse: [self sing].</b></blockquote>
&nbsp;&nbsp;&nbsp;&nbsp; Which assumes another private method, which builds
on our first private method.&nbsp; You can see how having the lyrics factored
out into a separate method is useful, as we can access them as needed to
sing loudly (uppercase) or quietly (lowercase).
<br><i>[ex1h]</i>
<blockquote><b>mySing: someLyrics inManner: anAdjective withTitle: aTitle</b>
<br><b>&nbsp;"Using simple logic here for illustrative purposes - if the
adjective is not 'loudly' or 'quietly' just ignore how we're being asked
to sing"</b>
<br><b>&nbsp;| tmpLyrics |</b>
<br><b>&nbsp;&nbsp;&nbsp; anAdjective = 'loudly'</b>
<br><b>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; ifTrue: [tmpLyrics :=
someLyrics asUppercase].</b>
<br><b>&nbsp;&nbsp;&nbsp; anAdjective = 'quietly'</b>
<br><b>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; ifTrue: [tmpLyrics :=
someLyrics asLowercase].</b>
<br><b>&nbsp;&nbsp;&nbsp; self mySing: tmpLyrics withTitle: aTitle</b></blockquote>
&nbsp;&nbsp;&nbsp;&nbsp; I'm leaving out the <b>whatIsMyHeight</b> method,
as it's just more of the same of what we've covered.&nbsp; Note the simple
conditional logic that we've used here.&nbsp; This is something that can
be avoided by programming methods like double dispatching, but that's beyond
the scope of this article.&nbsp; Avoiding conditional logic is often cited
as one of the benefits of OO programming.&nbsp; To illustrate, image that
we have 30 different songs that we needed to sing, this would lead us to
have 30 different <b>ifTrue</b> statements, or a CASE statement (most Smalltalks
don't even have a CASE statement) with 30 cases.&nbsp; Then if we needed
to add 5 more songs, we'd need to track down all the places where we used
the 30 cases and add our additional 5; chances are there's more than one
place where there are these 30 cases, and you'll eventually have problems
keeping all the cases in sync.&nbsp; For simplicity though, we're using
conditional logic for illustrative purposes.
<br>&nbsp;
<h2>
<a NAME="lookingForward"></a>Looking forward</h2>
&nbsp;&nbsp;&nbsp; The next article will cover OO thinking now that we've
covered many of the basics, it'll cover some of the advantages and differences
of OO programming from other types of programming.
<h2>
<a NAME="sweetSqueak"></a>A Sweet Squeak - Luke, use the debugger</h2>
&nbsp;&nbsp;&nbsp; This section won't explore/explain code or example,
but merely present a neat thing to try out.&nbsp; This month, we're going
to get into debugging, as this is something I consider a sweet characteristic
of Smalltalk.&nbsp;&nbsp; Part and parcel of not having a compile-link-run
cycle in programming, is that you can debug and correct your programs in
realtime from the debugger.
<br>&nbsp;&nbsp;&nbsp; To illustrate this, we're going to insert a <b>halt</b>
message somewhere in <b>aPerson's </b>code.&nbsp; Edit the <b>sing</b>
method, and as the first line put <b>self halt.&nbsp; </b>So your method
should look like:
<br><i>[ex2]</i>
<p><b>&nbsp;&nbsp;&nbsp; self halt.</b>
<br><b>&nbsp;&nbsp;&nbsp; self mySing: 'Do be do be doooooo.' withTitle:
'A bad impression of Sinatra'.</b>
<p><b>&nbsp;&nbsp;&nbsp; </b>Then ask your person to sing by doing: <b>Person
new sing</b>, you'll see the debugger:
<br><img SRC="misc/steffler/debugger1.png" >
<p>&nbsp; Click on the Debug button, and click on the 2nd method on the
method stack. For the read-along folks, you'll see:
<br><img SRC="misc/steffler/debugger2.png" >
<p><b>&nbsp;&nbsp; </b>Now, you can delete the <b>self halt.</b>, then
<b>middle-click>accept</b>
- at this point your code is updated such that any requests to the <b>sing</b>
method get the new version. Now you can continue execution by moving your
pointer over the top pane, and
<b>middle-click>proceed</b>
<br>&nbsp;&nbsp;&nbsp; This can be a very powerful way of programming/debugging
your code.&nbsp; Remember, <u>the debugger is your friend</u> - many new
Smalltalkers don't use the debugger to it's full advantage because the
compile-link-run cycle is so ingrained.&nbsp; Following this model, you
use the debugger to step in and over code until you see the problem, then
you close the debugger and go back to your browser to make the code update,
then try running the code again.&nbsp; Why not just make the code update
while you're in the debugger and continue on your merry way!?&nbsp; Another
very powerful technique can be to insert a breakpoint in a troublesome
part of the code, then manually change the live objects to simulate various
conditions to help you debug (scribbling temp values for different scenarios
on scaps of paper can become a thing of the past).&nbsp; Sometimes it is
necessary to begin execution from the start because the context will be
so different, but more times than not you can just fix things right in
your debugging session.
<h2>
<a NAME="questionsAndAnswers"></a><b>Questions and Answers</b></h2>
No questions this month, I suppose everything was crystal clear last month
;-)
<h2>
<a NAME="articleGlossary"></a><b>Article Glossary</b></h2>
This is a glossary of terms that I've used for the first time in this series,
or a term that I want to refine.&nbsp; If you don't see a term defined
here, try the <a href="http://www.magma.ca/~jagwar/makingSmalltalkForwardingPage.html">ongoing
glossary</a>.
<p><b>Base Classes</b>
<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; The base Smalltalk classes
that you start a clean image with.&nbsp; For example, Object, Boolean,
Magnitude, Stream, etc.&nbsp; Though you can (and sometimes need to) do
base class changes, it's generally not advised as it's very easy to mess
up the image or to break forwards compatibility.
<p><b>Namespace</b>
<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; A namespace is much what
it sounds like - a finite space that names can be defined and identified
in.&nbsp; For example, if you're writing a program and you wanted to define
a class called Object, you'd be out of luck as the class Object already
exists. If you were able to define a second class called Object, how would
the computer know the difference between the two?&nbsp; In most Smalltalks
there is a single namespace (VisualWorks Smalltalk is the notable exception).
<p><b>Namespace collision</b>
<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; When two companies/groups/people
try to name thier classes with the same name, or define methods off of
a class with the same name.&nbsp; To help avoid namespace collision not
only within your own projects, but from other companies like third party
vendors, it's a common practice to prefix your classes with some acronym,
for example, if you work for MegaCorp you might prefix all your classes
with 'Mc'
<p><b>Refactor</b>
<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; To change/update/reorganize
your code to make it (hopefully ;-) cleaner, faster, more robust.&nbsp;
Refactoring typically moves around responsibilities and/or makes larger
methods into smaller methods.
<br>&nbsp;
<h2>
<a NAME="footnotes"></a><b>Footnotes</b></h2>
[1] More accurately, it will overwrite, but not remove any existing structure/behaviour.&nbsp;
For example, if you have a method on a class that doesn't exist in the
corresponding class for the filein, then the method will still be there
after the filein.&nbsp; Change sets are a little different, and we'll discuss
them in a future article if there's enough interest.
<p>[2] Well, this isn't technically true.&nbsp; As in many other parts
of this series I'm making a simplifying statement/assumption.&nbsp; To
be more clear, for the purposes of beginners it simplifies things to consider
Object the root object of Smalltalk.
<br>To be more precise, Smalltalk has an elegant method for bootstrapping
its class hierarchy that's rooted in meta classes and circular definition.&nbsp;
If you don't understand the next sentence, don't worry because typically
it's nothing you need worry about for regular Smalltalking.&nbsp; Briefly,
in Squeak there's actually a class called ProtoObject that is the super
class of Object, and ProtoObject inherits from nil - the sole instance
of UndefinedObject, which inherits from Object.&nbsp; Other Smalltalk flavours
have something similar to this.
<!-- *** BEGIN copyright *** -->
<P> <hr> <!-- P -->
<H5 ALIGN=center>
Copyright &copy; 2001, Jason Steffler.<BR>
Copying license <A HREF="../copying.html">http://www.linuxgazette.com/copying.html</A><BR>
Published in Issue 62 of <i>Linux Gazette</i>, February 2001</H5>
<!-- *** END copyright *** -->
<!--startcut ==========================================================-->
<HR><P>
<CENTER>
<!-- *** BEGIN navbar *** -->
<IMG ALT="" SRC="../gx/navbar/left.jpg" WIDTH="14" HEIGHT="45" BORDER="0" ALIGN="bottom"><A HREF="silva.html"><IMG ALT="[ Prev ]" SRC="../gx/navbar/prev.jpg" WIDTH="16" HEIGHT="45" BORDER="0" ALIGN="bottom"></A><A HREF="index.html"><IMG ALT="[ Table of Contents ]" SRC="../gx/navbar/toc.jpg" WIDTH="220" HEIGHT="45" BORDER="0" ALIGN="bottom" ></A><A HREF="../index.html"><IMG ALT="[ Front Page ]" SRC="../gx/navbar/frontpage.jpg" WIDTH="137" HEIGHT="45" BORDER="0" ALIGN="bottom"></A><A HREF="http://www.linuxgazette.com/cgi-bin/talkback/all.py?site=LG&article=http://www.linuxgazette.com/issue62/steffler.html"><IMG ALT="[ Talkback ]" SRC="../gx/navbar/talkback.jpg" WIDTH="121" HEIGHT="45" BORDER="0" ALIGN="bottom" ></A><A HREF="../faq/index.html"><IMG ALT="[ FAQ ]" SRC="./../gx/navbar/faq.jpg"WIDTH="62" HEIGHT="45" BORDER="0" ALIGN="bottom"></A><A HREF="lg_backpage62.html"><IMG ALT="[ Next ]" SRC="../gx/navbar/next.jpg" WIDTH="15" HEIGHT="45" BORDER="0" ALIGN="bottom" ></A><IMG ALT="" SRC="../gx/navbar/right.jpg" WIDTH="15" HEIGHT="45" ALIGN="bottom">
<!-- *** END navbar *** -->
</CENTER>
</BODY></HTML>
<!--endcut ============================================================-->