NamespaceBrowser Tutorial

 

The NamespaceBrowser is a modified Squeak browser that lets you manipulate Namespaces and Packages.

 

Getting started

 

Ask me for an image.

 

Basic Concepts

 

Okay... beer with me:

 

Namespaces

 

A Namespace is a hierarchically organised collection of classes and "global variables". Namespaces can contain more namespaces. An example of a Namespace is "Collections". An example of a Namespace in "Collections" is "Strings". Another way to refer to "Strings" is "Collections.Strings".

 

Namespaces each have an "import list" which is a list of other namespaces that the methods in that Namespace can refer to. The import list could refer to Namespaces in other packages. This is the only way a Namespace can gain access to another Namespace (except for when one namespace is the child of another).

 

Packages

 

A Package typically contains code related to one particular subject, such as "Collections".

 

A Package is a Namespace. The Package class is a subclass of Namespace. It forms the root of a hierarchy of Namespaces.

 

A Package is a "live object"; this is the final stage where code is now ready to be used. You create instance of objects directly out of the classes in a package.

 

It is possible to have multiple versions of the same package installed in an image at the same time. Each package contains unique classes even though the classes have the same name.

 

Packages have dependencies on other packages. Packages depend on exact versions of other packages, so that the behaviour of code is guaranteed to behave exactly the same as the programmer wrote and tested it. It is the programmer's responsibility to upgrade software, not the user.

 

PackageVersions

 

A "Package"  is intended to only store the compiled code, not the source code. In the current implementation, this isn't the case, but will be at some point in the future.

 

A "PackageVersion" (TODO: rename to PackageSource?) is intended to store the source code and other metadata such as license, author, date, version, and so forth of a Package. In the current implementation, it does not yet store the source code. Every Package is generated from one and only one PackageVersion.

 

End users will have no use for PackageVersions, PackageRepositories or PackageManagers because these are all developer's tools. These tools can be removed from the image. In this case, if a user no longer has any objects made from classes in a particular Package, that Package will be garbage collected by the VM.

 

PackageRepositories

 

A PackageRespository stores a list of PackageVersions. This is like a code repository in a version control system. Each PackageRepository stores a PackageVersion, plus all the older versions of that PackageVersion.

 

Except for the working copy, these are all read-only (although in the current version, I rely on the user's honesty in not editing them).

 

The latest version is the "head"; it is the most recent PackageVersion.

The working copy can be created if you want to edit this package. It will create a new, writable version of the package.

 

PackageManager

 

The PackageManager is a list of PackageRepositories, which each contain a package of some sort.

 

 

Using the tools

 

The PackageManager is a tool that lets you manage packages that are currently available to your set of development tools. To open the PackageManager, do:

 

PackageManagerTool open

 

This should pop up a window that looks similar to the following:

 

TODO: insert image.

 

Here you can see a list of currently installed PackageRepositories.

 

The PackageManager doesn't necessarily show all packages that are available in your image. Rather, it only shows Packages that your development tools (in particular, the NamespaceBrowser) will use to search for particular classes.

 

If you right-click on the PackageManager, the following context menu pops up:

 

TODO: insert image.

 

Any tools that you open from this PackageManager will be associated with this PackageManager and will make use of it in various ways.

 

We will start by creating a Package. Right-click on the PackageManager and use the context menu to create a new PackageRepository called "CustomerManagement".

 

You can now do several things with your new PackageRepository. Use the context menu to browse a new working copy.

 

TODO: insert image.

 

The NamespaceBrowser lets you edit a single Package's contents. You'll notice two differences from a standard Browser: the system category view has been replaced by a hiearchy of Namespaces, and there's an extra pane to the left of the code which shows the currently selected Namespace's "import list".

 

We will start by creating a Namespace hiearchy. Right-click in the top-left pane and create a new Namespace called "Customers". Create two sub-Namespaces of "Customers" called "AddressManagement" and "History". These sub-namespaces will be referred to as Customers.AddressManagement and Customers.History.

 

 

Creating classes.

 

Now create a class in Customers.AddressManagement called "Address" by selecting Customers.AddressManagement, editing the text in the code pane and accepting the changes. You'll notice that the text in the code pane is a bit different from a standard Browser. Pooled variables have been removed because the same functionality can be achieved using namespaces. In the code, "self" is an instance of CodeBuilder.

 

Also create a class in Customers.History called "RecentEvents". Now we are going to refer to a class in one Namespace from another. Go back to Customers.AddressManagement.Address and add a method called "recentEvents". The method body is as follows:

 

recentEvents
^ RecentEvents new.

This should automatically add the Customers.History Namespace to the import list.

 

The import list contains a list of Namespaces that are searched for to find classes. There are only two places that are searched when looking for a class: the local namespace, and namespaces in the import list. If neither of these contain the class you use in code, then the method will not compile. This includes other classes in the same Package: if they are not in the import list, they cannot be referred to.

 

The NamespaceBrowser helps you in this regard by automatically searching the PackageManager that it is associated to for the class, and then automatically including other namespaces in the import list. These namespaces could be in the local package or in a completely different package. If a namespace from a different package is included, the resulting link is to a particular version of that other package, meaning that if a different version of that package is loaded into the image as well then the import will have absolutely no effect on the working of your code. Your code will still be bound to the old version of that package. You can upgrade dependencies using the PackageManager. Particular versions of packages are bound like this so that when somebody deploys your code, it will be deployed against exactly the same packages it was written and tested on.

 

Now we will use a dotted syntax to specify the class. Remove the method that you used before, and delete the entry in the import list. Now add this method:

 

recentEvents
^ Customers.History.RecentEvent new.

 

You will notice that this will include the CustomerManagement package in the import list. The Package class is a subclass of Namespace and always make up the root of a set of Namespaces relevant to that Package.

 

 

The dotted notation is always relative to either the local Namespace or any Namespace in the import list. For example, the following will make the NamespaceBrowser automatically put the Customers namespace in your import list:

 

recentEvents
^ History.RecentEvent new.

You can also manually edit the import list. Namespaces can be dragged and dropped from other NamespaceBrowsers or import lists, and entries in the import list can be removed. For convenience, the import list is presented as a hiearchy - you can open up a particular entry to see what can be referred to.

 

Namespaces replace pooled variables. They are useful for storing constants. To bind a global variable to a Namespace, you will need to open up an inspector on a Namespace and manually add it. Remember that any bindings are made at compile time, so that if a global variable changes to another object, code will need to be rebound to see these changes (TODO: doesn't Squeak currently do better than that?).

 

Resolving conflicts.

 

Upgrading package dependancies.

 

 

 

 


Page Information

  • 2 weeks ago [history]
  • View page source
  • You're not logged in
  • No tags yet learn more

Wiki Information

Recent PBwiki Blog Posts