Metacello Baselines
Metacello is Smalltalk's dependency manager: it describes which packages a project has, how they depend on each other, which external projects are required, and in which order to load them.
29.1 What Metacello does
Metacello is Smalltalk's dependency manager: it describes which packages a project has, how they depend on each other, which external projects are required, and in which order to load them. A baseline is a class named BaselineOf<Project> with a baseline: method.
29.2 Writing a baseline
Platform-specific sections use spec for: #pharo do: [...], spec for: #squeak do: [...], spec for: #gemstone do: [...], or version-specific attributes such as #'pharo12.x'.
BaselineOf << #BaselineOfBank
slots: {};
package: 'BaselineOfBank'
BaselineOfBank >> baseline: spec
<baseline>
spec for: #common do: [
"External dependencies"
spec
baseline: 'NeoJSON'
with: [ spec repository: 'github://svenvc/NeoJSON:master/repository' ].
spec
baseline: 'Teapot'
with: [ spec repository: 'github://zeroflag/Teapot:master/source' ].
"Our packages and their dependencies"
spec
package: 'Bank-Core' with: [ spec requires: #( 'NeoJSON' ) ];
package: 'Bank-Tests' with: [ spec requires: #( 'Bank-Core' ) ];
package: 'Bank-Web' with: [ spec requires: #( 'Bank-Core' 'Teapot' ) ].
"Groups: named subsets to load"
spec
group: 'Core' with: #( 'Bank-Core' );
group: 'Tests' with: #( 'Bank-Tests' );
group: 'Web' with: #( 'Bank-Web' );
group: 'default' with: #( 'Core' 'Tests' 'Web' ) ]29.3 Loading a project
Repository URL forms: github://user/repo:branchOrTag/subdir, gitlab://…, bitbucket://…, gitlocal://path, filetree://path, tonel://path, and HTTP Monticello URLs.
Metacello new
baseline: 'Bank';
repository: 'github://myuser/my-bank:main/src';
load. "loads the 'default' group; use load: #( 'Core' ) for a group"29.4 Handling conflicts and locks
Metacello new
baseline: 'Bank';
repository: 'github://myuser/my-bank:main/src';
onConflictUseIncoming; "or onConflictUseLoaded"
load.
"Lock a dependency to a local working copy during development"
Metacello new
baseline: 'NeoJSON';
repository: 'gitlocal:///home/me/src/NeoJSON/repository';
lock.29.5 Pre/post load actions
Inside a package spec, spec preLoadDoIt: #selector and spec postLoadDoIt: #selector run baseline methods before or after loading (e.g., to initialize default settings).
29.6 ConfigurationOf (legacy)
Before Git, projects used ConfigurationOf<Project> classes with explicit numbered versions. You will still meet them in older projects; new projects should use baselines plus Git tags for versions.
🧪 Part II Exercises
Define a Fraction-like class Rational (named MyRational to avoid clashes) with numerator, denominator, normalization in the constructor, +, *, =, hash, <, and printOn:. Make it a subclass of Magnitude and check you get max: and between:and: for free.
Build a Shape hierarchy (Circle, Rect, Triangle) with an abstract area and perimeter; sort a collection of shapes by area with sorted: #area ascending.
Demonstrate the difference between a class variable and a class-side instance variable with a per-class instance counter in a three-level hierarchy.
Write a LoggingProxy (subclass of ProtoObject) that counts every message sent to the wrapped object, and use it to find how many messages sorted sends to an Array.
Explore metaclasses: write expressions showing the class, superclass, and metaclass chain for 3, Object, Object class, and Metaclass; draw the diagram.
Given a text file, compute the 10 most frequent words (case-insensitive) using a Bag, substrings, and sortedCounts; write the report to a new file with FileSystem.
Implement a Stack and Queue with TDD by starting from tests and creating all methods in the debugger.
Define an exception hierarchy for a library system (LibraryError, BookNotAvailable, MemberSuspended), signal them from domain methods, and test them with should:raise:.
Use retry to implement a function that re-attempts a flaky operation up to 5 times with an increasing Delay, then gives up with a custom error.
Put your Part II code in Git with Iceberg in Tonel format, write a BaselineOf with Core and Tests groups, and load it into a fresh image with Metacello.