|

|
Everything you have accomplished so far has been done
using existing Smalltalk objects and their methods in a workspace.
However, to really take advantage of the Smalltalk development environment,
in order to make the code do more, you need to create your own objects and
methods.
|
|

|
This lesson explains how to use the
System Browser in order for you to create your own packages, classes,
protocols and methods. By the end of this lesson, your code to view web hits
for a given directory of log files will work just as it did in the previous
lesson. However, your code will be in a more efficient, powerful and re-usable
format.
|
|

|
Moving code from a Workspace to the System
Browser (where you will have your own classes and methods) requires some
tweaking. This is necessary in order for the code to execute properly. This
lesson covers that procedure.
|
|

|
1. From the main VisualWorks Launcher
window, click the fourth button on the Toolbar or select the menu
option Browse >> System.

Figure 7-1. The System Browser Toolbar Option

Figure 7-2. The System Browser
A window
will appear with Packages in the title, which is a bit misleading. The
dialog you are looking at is called the System Browser and by default,
it displays packages that currently exist in your VisualWorks library.
You don't know it yet, but this is the most powerful tool in the Smalltalk
development environment. Although it is not the best analogy (nor is it a
fair one), the System Browser can be compared to what other
developnment languages call an IDE (Integrated Development Environment). It
is THE main tool used by Smalltalk developers. Because it is so
powerful, there's way too much to explain at this stage so we will proceed
right to the steps we need for now. However, if you would like to learn more
a little more about this tool, you can view the System Browser primer.
|
|

|
Proceed to the System Browser
primer.
|
|
|
From the System Browser menu, select Browse
>> System. Below is a graphic that summarized how the System
Browser, in package mode, is organized:

Figure 7-3. How the System Browser (packages) is organized
You can
change the default mode from Packages to Parcels by going to
the main launcher window and select System >> Settings from the
main menu. Then select Tools >> Browser from the list of options
in the left pane and on the right you will see a drop-down selection list for
default browser type. We recommend that you stay with the Packages view.

Figure 7-3a. Changing the System Browser default type
Packages and protocols are just mechanisms for organizing the classes and
methods. Packages are also an aspect of the version control system, but
that's beyond the scope of this tutorial. It will take a while to start
remembering which classes belong to which Packages and which methods belong
to which protocols but let's not worry about that for now. We're just about
ready to start coding, but before we do, there's just one more catch - Namespaces.
|
|

|
What is a Namespace?
A Namespace is a difficult concept to explain so
instead let's use an analogy. Suppose there was this building (for the sake
of the analogy, this building would represent your Smalltalk image, the
library of all Smalltalk methods). In this building, you are going to allow
people to enter; however, no two people who enter can have the same name. For
example, as soon as you allow BOB to enter the buildling, no other BOB
can enter. A problem would arise if we allowed a second BOB into the
building. Suppose SUSAN walks in and says "Hey BOB! Let's
do lunch." Which BOB does she mean?
So here's the solution. You are allowed to create as many rooms in this
building as you want. Now SUSAN can ask "Hey BOB in room
A. Let's do lunch." and the conflict is solved.
This is how the Smalltalk image (class library) is organized. Instead of
having all of the existing (delivered) classes and the new ones you create
living in the same (one room) building, they are sequestered off into
separate rooms. These separate rooms would represent namespaces. When
you create your own classes, it is highly recommended that you create a
separate room (namespace) for them. The reason for this is quite simple.
Since you can make up your own names for your classes, it is likely that you
and another programmer might want to use the same name for your classes even
though they may do entirely different things. This is called a collision.
In the past, people used a "prefixing" naming convention to avoid
collisions, but this discouraged reuse so namespaces were invented.
Normally, before you choose your classes, protocols and methods, you would
first create a namespace where they all will belong. Not that this is a
complicated procedure, but for the scope of this tutorial, in order to keep
things very simple, we will not create our own namespace. We will add all of
our classes into an existing namespace, and use a single package. That
namespace is called Smalltalk.
|
|

|
2. If you have closed the System Browser, re-open it
and select the first package listed (Base VisualWorks) in the list of
packages. A list of classes will appear in the class list to the right of the
packages. In the bottom (method) pane, the System Browser will display
a template for defining a new class in the method code area. However, since
you selected the Base VisualWorks package, that will be the name of
the package listed in the code area. (Base VisualWorks is actually a bundle -
which contains other packages. We won't be going into that in this tutorial).
The System Browser should look like the one below:

Figure 7-4. The System Browser with the "New Class"
template.
3. The next step is to create a new package, which is where we will
save all of the code you'll create. In the browser, pull down the
"Package" menu item, and select "New Package". You should
see the following:

Name your package WebLogStats.
The next step is to create a new class. The easiest way
to do that is to use the class creation tool. In the the open browser, with
the new package selected, pull down the "Class" menu, and select
"New Class". You should see a dialog that looks like what's below;
fill in the appropriate fields as shown. Most of the fields in the dialog are
optional, and you can allow them to default for now:

Once you click "Ok", you should see a new class defined in the
browser, with the definition as seen below
Smalltalk defineClass: #WebLog superclass: #{Core.Object} indexedType: #none private: false instanceVariableNames: 'filter logDirectory ' classInstanceVariableNames: '' imports: '' category: 'WebLogStats'
4. When
you selected "Ok", the class was compiled and placed into the new
WebLogStats package. You'll notice that two method protocols were created for
you - "accessing" and "initialize-release". By default,
the class creation dialog generated basic methods for accessing the instance
variables, as well as an initialization method. We'll be looking at (and
modifying) that code below. You should now see a window that looks like this:

Figure 7-5b. Our new package (WebLogStats) with our new class WebLog
Making the
class name and package name just slightly different makes things easier to
differentiate. You do not need to call your class WebLog (you could
have used just WebLogStats but this way, you'll know it's a class).
Note the line regarding instanceVariableNames. These are variables
that belong to each instance. Once set, their values remain for as long as
the object remains.
5. Click the WebLog (Class) so that it is highlighted, then
click the Class tab above the protocol pane. Again, you'll see that a
method category (and a method) have been auto-generated. Select the protocol
"instance creation" and the method "new". If you didn't
have this generated, then do the following:
6. Now <Operate-Click> in the protocol pane. Select New...
A dialog box will appear asking you to enter a new protocol name. When it
comes to protocol names, there is a de-facto naming convention amongst all
Smalltalkers for "common" protocols to which everyone agrees. Enter
instance creation and click OK.
Note that
some text has appeared in the bottom pane. This is a "template" for
you to use when creating methods.
You should see a window like the one below.

Figure 7-6. Our new protocol (instance creation) viewed in the
Browser
7. Make sure the protocol tab is set to Class. If the new method was not automatically
generated, create it by replacing the following text:
message selector and argument names
"comment stating purpose of message"
| temporary variable names |
statements
with
new
^super new initialize
8. Now <Operate-Click> in the bottom pane and select Accept.
You can also use the keyboard shortcut ctrl-s. This will "compile"
the code you just entered and barring any typos, the new method will
appear in the method pane.
You should see a window like the one below.

Figure 7-7. Our new method (new) viewed in the Browser
|
|

|
What the heck does "^super new initiaize" mean?
Proceed to the super primer.
|
|

|
9. Click the Instance tab above the protocol pane.
Note that
your class definition text has reappeared.
10. Now <Operate-Click> in the protocol pane.
Select New... A dialog box will appear asking you to enter a new
protocol name. When it comes to protocol names, there is a de-facto naming
convention amongst all Smalltalkers for "common" methods to which everyone
agrees. If you let the class creation dialog generate code, there's already
an "initialize-release" protocol category. If there's not, do the
next step. Enter initialize-release and click OK. Note that you will
already have this protocol and an "initialize" method if you let
the creation dialog generate it.
Note that
some text has appeared in the bottom pane. This is a "template" for
you to use when creating methods. If you already have the
"initialize" method, don't worry - you can overwrite it in place,
with the code you'll need. In the examples below, you may need to change the
VW home directory - we are using "c:\vw7.4" here. Change that as
appropriate for your platform and installation. Again, if you let the class
creation dialog generate code, you'll see a default "initialize"
method.
You should see a window like the one below.

Figure 7-8. The default method generated for you
11. Replace the text in the method code area with the following:
initialize
"initialize the WebLog. Set the logDirectory variable."
logDirectory := 'c:\vw7.4'.
The initialize
method is one of those "common" methods that
"unofficially" belongs to the initialize-release protocol.
Also, now would be a good time to modify the value of the instance variable
to the directory where the log files exist (otherwise your code will not work
properly).
12. Before you <Operate-Click> in the bottom pane and
select Accept (or type ctrl-s), you may want to change the string c:\vw7.4
to the actual directory that contains your log files. This will
"compile" the code you just entered and barring any typos, the initialize
method will appear in the Method pane.
You should see a window like the one below.

Figure 7-9. Our new method (initialize) viewed in the Browser
13. Make sure the Instance tab above the protocol pane is still
selected. Now <Operate-Click> in the protocol pane. Select New...
A dialog box will appear asking you to enter a new protocol name. Enter testing
and click OK.
Note that
the "template" for creating methods appears.
14. Replace the text in the method code area with the following:
viewDirectory
| workingDir contents |
workingDir := logDirectory asFilename.
contents := workingDir directoryContents.
contents do: [ :each | Transcript show: each printString; cr. ]
15. Now <Operate-Click> in the bottom pane and select Accept.
This will "compile" the code you just entered and barring any
typos, the viewDirectory method will appear in the Method pane.
You should see a window like the one below (probably not formatted; the code
presented below is in "standard" Smalltalk formatting style).

Figure 7-10. Our new method (viewDirectory) viewed in the
Browser
|
|

|
16. Open a Workspace and make sure the Transcript
is visible too.
Enter WebLog new viewDirectory then Do it.
See? The code still works. You are now using a Workspace to test the
objects you just created.
|
|

|
17. Make sure the Instance tab above the protocol pane is
still selected. Now <Operate-Click> in the protocol pane.
Select New... A dialog box will appear asking you to enter a new protocol
name. Enter private and click OK.
Note that
the "template" for creating methods appears.
18. Replace the text in the method code area with the following:
showHits: aFile
| myFile myStream myLine addrIP mySet |
mySet := Set new.
myFile := logDirectory asFilename construct: aFile.
myStream := myFile readStream.
[ myStream atEnd ] whileFalse:
[myLine := myStream upTo: Character cr.
addrIP := myLine copyUpTo: $,.
mySet add: addrIP.].
myStream close.
^mySet size.
19. Now <Operate-Click> in the bottom pane and select Accept.
This will "compile" the code you just entered and barring any
typos, the showHits method will appear in the Method pane. The "construct:"
method above lets us create filename objects in a platform neutral way - the
code above will work the same way on Unix, Linux, Windows, and Macintosh
platforms.
You should see a window like the one below.

Figure 7-11. Our new method (showHits) viewed in the Browser
|
|

|
Methods in Smalltalk are like subroutines or functions in
other languages. The COBOL language calls them "procedures" and
most BASIC dialects call them "SUBs". However, the term "function"
is commonly used when a routine will return or pass back some value. In
Smalltalk, when you want to "return" something, you use the caret (^) sign.
Whenever you have an expression that uses the return caret, remember
to always evaluate the entire expression first. The actual "return"
is the very last thing that happens. So an expression like ^mySet size,
Smalltalk will evaluate mySet size (which probably produces a SmallInteger
instance) and returns that to the object that invoked the entire method.
|
|

|
If you are wondering about the proper formatting of the
code (indentations, line breaks, code blocks, etc.), you are free to use
whatever form you like. However, there is a defacto standard that VisualWorks
uses. The Browser provides an automatic formatting facility.
In the method area, <Operate-Click> and select Format. This
will "format" the code according to this defacto-standard.

Figure 7-12. The Format option on the menu

Figure 7-13. The code in a defacto-standard Smalltalk format
|
|

|
20. With the private protocol still selected, replace
the text in the method code area (it should be the showHits method)
with the following (don't worry - your code for the showHits method is
saved in memory):
getLogFiles
| workingDir contents xFound count |
workingDir := logDirectory asFilename.
contents := workingDir directoryContents.
contents do: [ :each |
xFound := each findString: filter startingAt: 1.
xFound > 0
ifTrue:[ count := self showHits: each.
Transcript show: each, ' . . . ', (count printString); cr. ].
].
Note that
we have resorted back to a simplified (non-compound) "filtering" logic.
Since the only files that begin with ws00 are our log files, then all
we have to do is search for files that begin with ws00. You will see
how this comes into play shortly when we initialize the filter
variable.
21. Now <Operate-Click> in the bottom pane and select Accept.
This will "compile" the code you just entered and barring any
typos, the getLogFiles method will appear in the Method pane.
You should see a window like the one below.

Figure 7-14. Our new method (getLogFiles) viewed in the Browser
|
|

|
What a minute! There's something new in that code I
haven't seen before - self. What does that do?
Find out more about self.
|
|

|
22. With the private protocol still selected, replace
the text in the method code area (it should be the getLogFiles method)
with the following:
start
filter := (Dialog request: 'Please enter a filter ' initialAnswer: 'ws00').
(filter size) > 0
ifTrue: [self getLogFiles]
23. Now <Operate-Click> in the bottom pane and select Accept.
This will "compile" the code you just entered and barring any
typos, the start method will appear in the Method pane.
You should see a window like the one below.

Figure 7-15. Our new method (start) viewed in the Browser
24. Open a workspace and enter the following:
Highlight all of this text, <Operate-Click> and select Do it.
The code
should now run just like it did in the previous lesson.

Figure 7-16. The results are still the same - the code is just in a
different location
|
|

|
Summary
Wow!
That was a long workshop but worth it. It seemed that way because you had to
do a lot of "up front foundation" work to create a package and some
standard protocols.
In the next lesson, you will learn how to save your work. And the lesson
after that, you will add more functionality to your class, namely to figure
out which web pages were the most popular (i.e. had the most hits).
You now should know how to:
|
Use
the System Browser to create a new package, class, protocol and
method
|
|
Identify
2 types of methods - Class and Instance
|
|
Format
code according to a Smalltalk defacto-standard
|
|
Test
your objects with a Workspace
|
|