6.2: The System Browser
- Page ID
- 36361
\( \newcommand{\vecs}[1]{\overset { \scriptstyle \rightharpoonup} {\mathbf{#1}} } \)
\( \newcommand{\vecd}[1]{\overset{-\!-\!\rightharpoonup}{\vphantom{a}\smash {#1}}} \)
\( \newcommand{\id}{\mathrm{id}}\) \( \newcommand{\Span}{\mathrm{span}}\)
( \newcommand{\kernel}{\mathrm{null}\,}\) \( \newcommand{\range}{\mathrm{range}\,}\)
\( \newcommand{\RealPart}{\mathrm{Re}}\) \( \newcommand{\ImaginaryPart}{\mathrm{Im}}\)
\( \newcommand{\Argument}{\mathrm{Arg}}\) \( \newcommand{\norm}[1]{\| #1 \|}\)
\( \newcommand{\inner}[2]{\langle #1, #2 \rangle}\)
\( \newcommand{\Span}{\mathrm{span}}\)
\( \newcommand{\id}{\mathrm{id}}\)
\( \newcommand{\Span}{\mathrm{span}}\)
\( \newcommand{\kernel}{\mathrm{null}\,}\)
\( \newcommand{\range}{\mathrm{range}\,}\)
\( \newcommand{\RealPart}{\mathrm{Re}}\)
\( \newcommand{\ImaginaryPart}{\mathrm{Im}}\)
\( \newcommand{\Argument}{\mathrm{Arg}}\)
\( \newcommand{\norm}[1]{\| #1 \|}\)
\( \newcommand{\inner}[2]{\langle #1, #2 \rangle}\)
\( \newcommand{\Span}{\mathrm{span}}\) \( \newcommand{\AA}{\unicode[.8,0]{x212B}}\)
\( \newcommand{\vectorA}[1]{\vec{#1}} % arrow\)
\( \newcommand{\vectorAt}[1]{\vec{\text{#1}}} % arrow\)
\( \newcommand{\vectorB}[1]{\overset { \scriptstyle \rightharpoonup} {\mathbf{#1}} } \)
\( \newcommand{\vectorC}[1]{\textbf{#1}} \)
\( \newcommand{\vectorD}[1]{\overrightarrow{#1}} \)
\( \newcommand{\vectorDt}[1]{\overrightarrow{\text{#1}}} \)
\( \newcommand{\vectE}[1]{\overset{-\!-\!\rightharpoonup}{\vphantom{a}\smash{\mathbf {#1}}}} \)
\( \newcommand{\vecs}[1]{\overset { \scriptstyle \rightharpoonup} {\mathbf{#1}} } \)
\( \newcommand{\vecd}[1]{\overset{-\!-\!\rightharpoonup}{\vphantom{a}\smash {#1}}} \)
\(\newcommand{\avec}{\mathbf a}\) \(\newcommand{\bvec}{\mathbf b}\) \(\newcommand{\cvec}{\mathbf c}\) \(\newcommand{\dvec}{\mathbf d}\) \(\newcommand{\dtil}{\widetilde{\mathbf d}}\) \(\newcommand{\evec}{\mathbf e}\) \(\newcommand{\fvec}{\mathbf f}\) \(\newcommand{\nvec}{\mathbf n}\) \(\newcommand{\pvec}{\mathbf p}\) \(\newcommand{\qvec}{\mathbf q}\) \(\newcommand{\svec}{\mathbf s}\) \(\newcommand{\tvec}{\mathbf t}\) \(\newcommand{\uvec}{\mathbf u}\) \(\newcommand{\vvec}{\mathbf v}\) \(\newcommand{\wvec}{\mathbf w}\) \(\newcommand{\xvec}{\mathbf x}\) \(\newcommand{\yvec}{\mathbf y}\) \(\newcommand{\zvec}{\mathbf z}\) \(\newcommand{\rvec}{\mathbf r}\) \(\newcommand{\mvec}{\mathbf m}\) \(\newcommand{\zerovec}{\mathbf 0}\) \(\newcommand{\onevec}{\mathbf 1}\) \(\newcommand{\real}{\mathbb R}\) \(\newcommand{\twovec}[2]{\left[\begin{array}{r}#1 \\ #2 \end{array}\right]}\) \(\newcommand{\ctwovec}[2]{\left[\begin{array}{c}#1 \\ #2 \end{array}\right]}\) \(\newcommand{\threevec}[3]{\left[\begin{array}{r}#1 \\ #2 \\ #3 \end{array}\right]}\) \(\newcommand{\cthreevec}[3]{\left[\begin{array}{c}#1 \\ #2 \\ #3 \end{array}\right]}\) \(\newcommand{\fourvec}[4]{\left[\begin{array}{r}#1 \\ #2 \\ #3 \\ #4 \end{array}\right]}\) \(\newcommand{\cfourvec}[4]{\left[\begin{array}{c}#1 \\ #2 \\ #3 \\ #4 \end{array}\right]}\) \(\newcommand{\fivevec}[5]{\left[\begin{array}{r}#1 \\ #2 \\ #3 \\ #4 \\ #5 \\ \end{array}\right]}\) \(\newcommand{\cfivevec}[5]{\left[\begin{array}{c}#1 \\ #2 \\ #3 \\ #4 \\ #5 \\ \end{array}\right]}\) \(\newcommand{\mattwo}[4]{\left[\begin{array}{rr}#1 \amp #2 \\ #3 \amp #4 \\ \end{array}\right]}\) \(\newcommand{\laspan}[1]{\text{Span}\{#1\}}\) \(\newcommand{\bcal}{\cal B}\) \(\newcommand{\ccal}{\cal C}\) \(\newcommand{\scal}{\cal S}\) \(\newcommand{\wcal}{\cal W}\) \(\newcommand{\ecal}{\cal E}\) \(\newcommand{\coords}[2]{\left\{#1\right\}_{#2}}\) \(\newcommand{\gray}[1]{\color{gray}{#1}}\) \(\newcommand{\lgray}[1]{\color{lightgray}{#1}}\) \(\newcommand{\rank}{\operatorname{rank}}\) \(\newcommand{\row}{\text{Row}}\) \(\newcommand{\col}{\text{Col}}\) \(\renewcommand{\row}{\text{Row}}\) \(\newcommand{\nul}{\text{Nul}}\) \(\newcommand{\var}{\text{Var}}\) \(\newcommand{\corr}{\text{corr}}\) \(\newcommand{\len}[1]{\left|#1\right|}\) \(\newcommand{\bbar}{\overline{\bvec}}\) \(\newcommand{\bhat}{\widehat{\bvec}}\) \(\newcommand{\bperp}{\bvec^\perp}\) \(\newcommand{\xhat}{\widehat{\xvec}}\) \(\newcommand{\vhat}{\widehat{\vvec}}\) \(\newcommand{\uhat}{\widehat{\uvec}}\) \(\newcommand{\what}{\widehat{\wvec}}\) \(\newcommand{\Sighat}{\widehat{\Sigma}}\) \(\newcommand{\lt}{<}\) \(\newcommand{\gt}{>}\) \(\newcommand{\amp}{&}\) \(\definecolor{fillinmathshade}{gray}{0.9}\)There are actually several browsers in Squeak: the standard system browser, the package browser, the Omnibrowser, and the Refactoring Browser. We will take a look at the standard system browser first, since the others are variations on it. Figure \(\PageIndex{1}\) shows the browser as it appears when you first drag it out of the Tools flap1.
The four small panes at the top of the browser represent a hierarchic view of the methods in the system, much in the same way as the NeXTstep File Viewer and the Mac OS X Finder in column mode provide a view of the files on the disk. The leftmost pane lists categories of classes; select one (say Kernel-Objects) and the pane immediately to the right will then show all of the classes in that category.
Similarly, if you select one of the classes in the second pane, say, Model (see Figure \(\PageIndex{2}\)), the third pane will show all of the protocols defined for that class, as well as a virtual protocol --all--, which is selected by default. Protocols are a way of categorizing methods; they make it easier to find and think about the behaviour of a class by breaking it up into smaller, conceptually coherent pieces. The fourth pane shows the names of all of the methods defined in the selected protocol. If you then select a method name, the source code of the corresponding method appears in the large pane at the bottom of the browser, where you can view it, edit it, and save the edited version. If you select class Model
, protocol dependents and the method myDependents
, the browser should look like Figure \(\PageIndex{3}\).
Unlike directories in the Mac OS X Finder, the four top panes of the browser are not quite equal. Whereas classes and methods are part of the Smalltalk language, system categories and message protocols are not: they are a convenience introduced by the browser to limit the amount of information that needs to be shown in each pane. For example, if there were no protocols, the browser would have to show a list of all of the methods in the selected class; for many classes this list would be too large to navigate conveniently.
Because of this, the way that you create a new category or a new protocol is different from the way that you create a new class or a new method. To create a new category, select new category
from the yellow button menu in the category pane; to create a new protocol, select new protocol
from the yellow button menu in the protocol pane. Enter the name of the new thing in the dialog, and you are done: there is nothing more to a category or a protocol than its name and its contents.
In contrast, to create a new class or a new method, you will actually have to write some Smalltalk code. If you deselect the currently selected category (most left pane) and the reselect it again, the main browser pane will display a class creation template (Figure \(\PageIndex{4}\)). You create a new class by editing this template: replace Object
by the name of the existing class of which you wish to create a subclass, replace NameOfSubclass
by the name that you would like to give to your new subclass, and fill in the instance variable names if you know them. The category for the new class is by default the currently selected category, but you can change this too if you like. If you already have the browser focussed on the class that you wish to subclass, you can get the same template with slightly different initialization by using the yellow button menu in the class pane, and selecting more. . . ⊳ subclass template
. You can also just edit the definition of an existing class, changing the class name to something new. In all cases, when you accept the new definition, the new class (the one whose name follows the #) is created (as is the corresponding metaclass). Creating a class also creates a global variable that references the class, which is why you can refer to all of the existing classes by using their names.
Can you see why the name of the new class has to appear as a Symbol
(i.e., prefixed with #) in the class creation template, but after the class is created, code can refer to the class by using the name as an identifier (i.e., without the #)?
The process of creating a new method is similar. First select the class in which you want the method to live, and then select a protocol. The browser will display a method-creation template, as shown in Figure \(\PageIndex{5}\), which you can fill-in or edit.
The button bar
The system browser provides several tools for exploring and analysing code. Those tools are most simply accessed from the horizontal button bar in the middle of the browser window. The buttons are labeled browse
, senders
, implementors
. . . Figure \(\PageIndex{5}\) shows the complete set.
Browsing code
The browse
button opens a new system browser on the class or method that is currently selected. It’s often useful to have multiple browsers open at the same time. When you are writing code you will almost certainly need at least two: one for the method that you are typing, and another to browse around the system to see what to type. You can also open a browser on a class named by any selected text using the CMD–b keyboard shortcut.
\(\bigstar\) Try this: in a workspace window, type the name of a class (for instance ScaleMorph), select it, and then press CMD–b. This trick is often useful; it works in any text window.
Senders and implementors of a message
The senders
button will give you a list of all methods that may use the selected method. With the browser open on ScaleMorph
, click on the checkExtent:
method in the method pane near the top right corner of the browser; the body of checkExtent:
displays in the bottom part of the browser. If you now press the senders button, a menu will appear with checkExtent:
as the topmost item, and below it, all the messages that checkExtent:
sends (see Figure \(\PageIndex{6}\)). Selecting an item in this menu will open a browser with the list of all methods in the image that send the selected message.
The implementors
button works in a similar way, but instead of listing the senders of a message, it lists all of the classes that implement a method with the same selector. To see this, select drawOn:
in the message pane and then bring up the “implementors of drawOn:” browser, either using the implementors
button, or the yellow button menu on the method pane, or just by typing CMD–m (for implementors) in the method pane with drawOn:
selected. You should get a method list window showing a scrolling list of 96 classes that implement a drawOn:
method. It shouldn’t be all that surprising that so many classes implement this method: drawOn:
is the message that is understood by every object that is capable of drawing itself on the screen. While viewing any one of these methods, try browsing the senders of the drawOn:
message: we found 63 methods that send this message. You can also bring up an implementors browser at any time by selecting a message (including the arguments if it is a keyword message) and typing CMD–m.
If you look at the send of drawOn:
in AtomMorph»drawOn:, you will see that it is a super
send. So we know that the method that will be executed will be in AtomMorph
’s superclass. What class is that? Click the hierarchy
button and you will see that it is EllipseMorph
.
Now look at the fifth sender in the list, Canvas»draw, shown in Figure \(\PageIndex{7}\). You can see that this method sends drawOn:
to whatever object is passed to it as an argument, which could potentially be an instance of any class at all. Dataflow analysis can help figure out the class of the receiver of some messages, but in general, there is no simple way for the browser to know which message-sends might cause which methods to be executed. For this reason, the “senders” browser shows exactly what its name suggests: all of the senders of the message with the chosen selector. The senders
button is nevertheless extremely useful when you need to understand how you can use a method: it lets you navigate quickly through example uses. Since all of the methods with the same selector ought to be used in the same way, all of the uses of a given message ought to be similar.
Versions of a method
When you save a new version of a method, the old one is not lost. Squeak keeps all of the old versions, and allows you to compare different versions and to go back (“revert”) to an old version. The versions
button gives access to the successive modifications made to the selected method. In Figure \(\PageIndex{8}\) we can see the versions of the mouseUp:
method that one of the authors created while writing the Quinto game described in Chapter 2.
The top pane displays one line for each version of the method, listing the initials of the programmer who wrote it, the date and time at which it was saved, the names of the class and the method, and the protocol in which it was defined. The current (active) version is at the top of the list; whichever version is selected is displayed in the bottom pane. If the diffs
checkbox is selected, as it is in Figure \(\PageIndex{8}\), the display also shows the differences between the selected version and the one immediately older. Buttons are also provided for displaying the differences between the selected method and the current version, and for reverting to the selected version. The prettyDiffs
checkbox is useful if there have been changes to layout: it pretty-prints both versions before differencing, so that the differences that are displayed exclude formatting changes.
The existence of the versions browser means that you never have to worry about preserving code that you think might no longer be needed: just delete it. If you find that you do need it, you can always revert to the old version, or copy the needed code fragment out of the old version and paste it into a another method. Get into the habit of using versions; “commenting out” code that is no longer needed is a bad practice because it makes the current code harder to read. Smalltalkers rate code readability extremely highly.
Hint
What if you delete a method entirely, and then decide that you want it back? You can find the deletion in a change set, where you can ask to see versions with the yellow button menu. The change set browser is described in Section 6.8.
Method overridings
The inheritance
button opens a specialized browser that displays all the methods overridden by the displayed method. To see how it works, display the ScaleMorph»defaultColor method and click inheritance
. This method definition overrides RectangleMorph»defaultColor, which itself overrides Morph»defaultColor, as shown in Figure \(\PageIndex{9}\). The colour of the inheritance
button depends on how the overriding occurs. The colours are explained in a help balloon:
- pink: the displayed method overrides another method but doesn’t use it;
- green: the displayed method overrides another method and uses it via
super
; - gold: the displayed method is itself overridden in a subclass;
- salmon: the displayed method overrides another method, and it itself overridden;
- violet: the displayed method overrides, is overridden, and makes a
super
-send.
Note that there are currently two versions of the inheritance browser. If you are using the version of the system browser based on the OmniBrowser framework, the inheritance button does not change colour, and the inheritance
browser looks different. It also displays more information: it shows not only the methods on the inheritance chain, but also their siblings. This version of the inheritance browser is shown in Figure \(\PageIndex{10}\).
The Hierarchy Browser
The hierarchy
button opens a hierarchy browser on the current class; this browser can also be opened by using the browse hierarchy
menu item in the class pane. The hierarchy browser is similar to the system browser, but instead of displaying the system categories and the classes in each category, it shows a single list of classes, indented to represent inheritance. The category of the selected class is displayed in the small annotation pane at the top of the browser. The hierarchy browser is designed to make it easy to navigate through the inheritance hierarchy, but does not show all of the classes in the system: only the superclasses and subclasses of the initial class are shown. In Figure \(\PageIndex{11}\), the hierarchy browser reveals that the direct superclass of ScaleMorph
is RectangleMorph
.
Finding variable references
The inst vars
and class vars
buttons help you find where an instance variable or a class variable is used; the same information is accessible from the yellow button menu items inst var refs
and class var refs
in the class pane. The menu also includes inst var defs
, which shows the subset of the instance variable references that assign to the variable. Once you click on the button or select the menu item, you will be presented with a dialog that invites you to choose a variable from all of the variables defined in the current class, and all of the variables that it inherits. The list is in inheritance order; it can often be useful to bring up this list just to remind yourself of the name of an instance variable. If you click outside the list, it will go away and no variable browser will be created.
Also available from the yellow button menu on the class pane is class vars
, which opens an inspector showing the class variables of the current class and their values, and class refs (N)
which displays a list of all of the methods that directly reference the current class.
Source
The source
button brings up the “what to show” menu, which allows you to choose what the browser shows in the source pane. Options include the source
code, prettyPrint
ed source code, byteCodes
and source code decompile
d from the byte codes. The label on the button changes if you select one of the other modes. There are other options too; if you let the mouse linger over the names, a help balloon will appear. Try some of them.
Note that selecting prettyPrint
in the “what to show” menu is not the same as prettyPrinting a method before you save it. The menu controls only what the browser displays, and has no effect on the code stored in the system. You can verify this by opening two browsers, and selecting prettyPrint
in one and source
in the other. In fact, focussing two browsers on the same method and selecting byteCodes
in one and decompile
in another is a good way to learn about the Squeak virtual machine’s byte-coded instruction set.
Refactoring
Did you notice the small R
at the end of the button bar?2 Although unobtrusive, this button gives access to one of the most powerful and important features of the Smalltalk environment. Clicking on R
gives you access to a hierarchy of menus for refactoring your code. The same refactoring engine is also available in several other ways, for example, through the yellow button menu in the class, method and code panes. Refactoring was formerly available only in a special browser called the refactoring browser, but it can now be accessed from any browser.
The browser menus
Many additional functions are available from the browser’s yellow button menu. Since yellow button menus are context-sensitive, each pane in the browser has its own menu. Even if the labels on the menu items are the same, their meaning is context dependent. For example, the category pane, the class pane, the protocol pane and the messages pane all have a file out
menu item. However, they do different things: the category pane’s file out
menu files out the whole category, the class pane’s file out
menu files-out the whole class, the protocol pane’s file out
menu files out the whole protocol, and the method pane’s file out
menu files-out just the displayed method. Although this may seem obvious, it can be a source of confusion for beginners.
Possibly the most useful menu item is find class. . . (f)
in the category pane. Although the categories are useful for the code that we are actively develop- ing, most of us do not know the categorization of the whole system, and it is much faster to type CMD–f followed by the first few characters of the name of a class than to guess which category it might be in. recent classes. . . (r)
can also help you quickly go back to a class that you have browsed recently, even if you have forgotten its name.
In the class pane, there are two menu items find method
and find method wildcard. . .
that can be useful if you want to browse a particular method. However, unless the list of methods is very long, it is often quicker to browse the --all-- protocol (which is the default), place the mouse in the method pane, and type the first letter of the name of the method that you are looking for. This will usually scroll the pane so that the sought-for method name is visible.
\(\bigstar\) Try both ways of navigating to OrderedCollection»removeAt:
There are many other options available in the menus. It pays to spend a few minutes working with the browser and seeing what is there.
\(\bigstar\) Compare the result of Browse Protocol
, Browse Hierarchy
, and Show Hierarchy
in the class pane menu.
Other class browsers
At the beginning of this section we mentioned another class browser: the package pane browser. This can be opened from the world menu: World ⊳ open. . . ⊳ package pane browser
. It’s basically the same as the class browser, but it knows about the naming convention for system categories. You will have noticed that the names of categories have two parts. For example, the ScaleMorph
class belongs to the Morphic-Widgets category. The package browser assumes that the part before the hyphen, Morphic
is the name of a “package”, and adds a fifth pane that allows you to browse only those categories in a particular package. However, if you select no package at all, then all the categories are available, just as with the ordinary four-pane browser.
Unfortunately, the meaning of the term package has changed since the package pane browser was developed. “Package” now has a more precise meaning, related to the Monticello packaging tool, as we will discuss in the next section. At present there is no tool that lets you browse packages as defined by Monticello, however there is one currently being developed.
The Squeak community is in the process of developing a whole new family of browsers based on a new, highly customizable framework called the OmniBrowser. The implementation of the OmniBrowser is worth looking at as a good example of object-oriented design, but from the outside, most of the OmniBrowser-based tools look very similar to the ones that we have just described. The main enhancement that you will notice in the Omni System Browser is the addition of virtual protocols. In addition to the traditional programmer-defined protocols, each class has a number of virtual protocols defined on it by definitional rules. For example, the --supersend-- protocol includes all of the methods that send to super, while the --required-- protocol lists all of the messages that are sent by the methods in the current class or its superclasses but not defined.
Browsing programmatically
The class SystemNavigation
provides a number of utility methods that are useful for navigating around the system. Many of the functions offered by the classic browser are implemented by SystemNavigation
.
\(\bigstar\) Open a workspace and do it
the following code to browse the senders of checkExtent::
SystemNavigation default browseAllCallsOn: #checkExtent: .
To restrict the search for senders to the methods of a specific class:
SystemNavigation default browseAllCallsOn: #drawOn: from: ScaleMorph .
Because the development tools are objects, they are completely accessible from programs and you can develop your own tools or adapt the existing tools to your needs.
The programmatic equivalent to the implementors
button is:
SystemNavigation default browseAllImplementorsOf: #checkExtent: .
To learn more about what is available, explore the class SystemNavigation
with the browser. Further navigation examples can be found in the FAQ (Appendix A).
Summary
As you have seen, there are many ways to navigate around Smalltalk code. You may find this confusing at first, in which case you can always fall back to the traditional system browser. However, we usually find that once beginners gain more experience with Squeak, the availability of different browsers becomes one of its most valued features, because they provide many ways to help you to understand and organize your code. The problem of understanding code is one of the greatest challenges of large-scale software development.
- If the browser you see looks different from the one we describe, then you might be using an image with a different default browser installed. See FAQ 5.
- That is, you will notice this button if you first load the AST and RefactoringBrowser packages from SqueakSource or use the Squeak-dev image.