8.8: Groups
- Page ID
- 45265
\( \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}\)Suppose now that the CoolBrowser project grows: A developer writes some tests for CoolBrowser-Addons
. These constitute a new package named CoolBrowser-AddonsTests
, which naturally depends on CoolBrowser-Addons
and CoolBrowser-Tests
, as shown in Figure \(\PageIndex{1}\).

We may want to load projects with or without tests. In addition, it is convenient to be able to load all of the tests with a simple expression like:
(ConfigurationOfCoolBrowser project version: '0.6') load: 'Tests'.
instead of having to explicitly list all of the test packages, like this:
(ConfigurationOfCoolBrowser project version: '0.6') load: #('CoolBrowser-Tests' 'CoolBrowser-AddonsTests').
Metacello provides the notion of group. A group is a collection of items; each item may be a package, a project, or even another group.
Groups are useful because they let you name sets of items for various purposes. Maybe you want to offer the user the possibility of installing just the core, or the core with add-ons and development features: you can make this easy be defining appropriate groups. Let’s go back to our example, and look at how we might define a new baseline, 0.6-baseline
that defines 6 groups, as shown in Figure \(\PageIndex{1}\). In this example, we create a group called Tests
that comprises CoolBrowser-Tests
and CoolBrowser-AddonsTests
.
To define a group we use the method group: groupName with: groupElements
. The with:
argument can be a package name, a project, another group, or a collection of those things. Here is the code corresponding to Figure \(\PageIndex{1}\).
ConfigurationOfCoolBrowser>>baseline06: spec <version: '0.6-baseline'> spec for: #common do: [ spec blessing: #baseline. spec repository: 'http://www.example.com/CoolBrowser'. spec package: 'CoolBrowser-Core'; package: 'CoolBrowser-Tests' with: [ spec requires: 'CoolBrowser-Core' ]; package: 'CoolBrowser-Addons' with: [ spec requires: 'CoolBrowser-Core' ]; package: 'CoolBrowser-AddonsTests' with: [ spec requires: #('CoolBrowser-Addons' 'CoolBrowser-Tests' ) ]. spec group: ’default’ with: #(’CoolBrowser-Core’ ’CoolBrowser-Addons’); group: 'Core' with: #('CoolBrowser-Core'); group: 'Extras' with: #('CoolBrowser-Addons'); group: 'Tests' with: #('CoolBrowser-Tests' 'CoolBrowser-AddonsTests'); group: 'CompleteWithoutTests' with: #('Core' 'Extras'); group: 'CompleteWithTests' with: #('CompleteWithoutTests' 'Tests') ].
Groups are defined in baselines. We are defining the groups in the baseline version, since a group is a structural component. Note that the default group will be used in the subsequent sections. Here the default group mentions that the two packages ’CoolBrowser-Core’ and ’CoolBrowser-Addons’ will be loaded when the method load is used.
Using this baseline, we can now define version 0.6 to be the same as version 0.5, except for the addition of the new package CoolBrowser-AddonsTests
.
ConfigurationOfCoolBrowser>>version06: spec <version: ’0.6’ imports: #(’0.6-baseline’)> spec for: #common do: [ spec package: 'CoolBrowser-Core' with: 'CoolBrowser-Core-BobJones.20'; package: 'CoolBrowser-Tests' with: 'CoolBrowser-Tests-JohnLewis.8'; package: 'CoolBrowser-Addons' with: 'CoolBrowser-Addons-JohnLewis.6'; package: 'CoolBrowser-AddonsTests' with: 'CoolBrowser-AddonsTests-JohnLewis.1'].
Examples. Once you have defined a group, you can use its name anywhere you would use the name of a project or package. The load:
method takes as parameter the name of a package, a project, a group, or a collection of those items. All of the following statements are possible:
(ConfigurationOfCoolBrowser project version: '0.6') load: 'CoolBrowser-Core'. "Load a single package" (ConfigurationOfCoolBrowser project version: '0.6') load: 'Core'. "Load a single group" (ConfigurationOfCoolBrowser project version: '0.6') load: 'CompleteWithTests'. "Load a single group" (ConfigurationOfCoolBrowser project version: '0.6') load: #('CoolBrowser-Core' 'Tests'). "Loads a package and a group" (ConfigurationOfCoolBrowser project version: '0.6') load: #('CoolBrowser-Core' 'CoolBrowser-Addons' 'Tests'). "Loads two packages and a group" (ConfigurationOfCoolBrowser project version: '0.6') load: #('CoolBrowser-Core' 'CoolBrowser-Tests'). "Loads two packages" (ConfigurationOfCoolBrowser project version: '0.6') load: #('Core' 'Tests'). "Loads two groups"
The groups default and 'ALL'. The default
group is a special one. The load
message loads the members of the default
group while loading the ALL
group will load all the packages. Moreover, by default, default
loads ALL
!
(ConfigurationOfCoolBrowser project version: '0.6') load.
loads just CoolBrowser-Core
and CoolBrowser-Addons
.
In the presence of a default
group, how do you load all the packages of a project? You use the predefined ALL
group, as shown below:
(ConfigurationOfCoolBrowser project version: '0.6') load: 'ALL'.
About Core, Tests and default
We often get at least two groups in a configuration: Core
(the real code) and Tests
(the associated tests). The question is what should be loaded by the default
group (remember, this is what gets loaded when you do not specify anything as a parameter).
By saying spec group: 'default' with: #('Core')
we say that by default we do not load tests.
Now if we do not specify any default
, it will take everything by default, hence it will be equivalent in our case with spec group: 'default' with: #('Core' ' Tests')
We believe that by using default it is good to load the tests as well. This is why, either we explicitly put the Tests
group in the default
group, or we do not specify a default
at all.