Metacello - more conditional elements

0 views
Skip to first unread message

Dale Henrichs

unread,
May 27, 2009, 2:37:46 PM5/27/09
to montice...@googlegroups.com
Yesterday when I did the version of MondrianVersionMap that conditionally included OmniBrowser, I used a technique that I think is really powerful, so I will go over it in a little more detail.

Basically, Mondrian requires that a version of OmniBrowser is loaded, so the OB dependency is very loose. In the current Mondrian loader, if the class OBNode doesn't exist then the latest version of OmniBrowser is loaded. Instead of making a hard requirement on a specific version of OmniBrowser, I decided to make the requirement conditional on the existence of the class OBNode.

If you recall from the earlier mail on conditional elements, Metacello has a default list of attributes: #common, #squeakCommon, #pharo, #squeak, and #gemstone. When a versionMap is instantiated on a platform, the attribute list is dynamically generated so that on Squeak, the attribute list would be:

#( common squeakCommon squeak)

on Pharo:

#( common squeakCommon pharo)

and on GemStone:

#( common gemstone)

For dynamically creating the package list on Pharo, the attribute list is processed in order. The methods whose pragmas match the pattern:

<packages: * attributes: #common>

are processed creating the initial MetacelloPackageVersionsSpec, then the methods matching this pragma pattern:

<packages: * attributes: #squeakCommon>

are processed and the MetacelloPackageVersionsSpec produced is merged into the initial MetacelloPackageVersionsSpec and so on with #pharo. Similar processing is done for the groups pragmas:

<groups: * attributes: * >

To make the requiredVersion for OmniBrowser conditional, I implemented the method #platformAttributes in MondrianVersionMap:

platformAttributes

| att |
att := super platformAttributes asOrderedCollection.
(Smalltalk hasClassNamed: #OBNode) ifFalse: [ att add: #omnibrowser ].
^att

which adds #omnibrowser to the end of attribute list when the class OBNode is absent. Then by adding a 'conditional' #version01OBGroups method:

version01OBFeatures
<features: '0.1' attribute: #omnibrowser >

^(MetacelloGroupsSpec for: self)
addFeature:
((MetacelloGroupSpec for: self)
groupName: 'core'
description: '';
addMember:
((MetacelloVersionMapSpec for: self)
versionMapClass: 'OBVersionMap';
version: '0.442';
loadList: { 'dev tools'. };
packagesSpec:
((MetacelloPackagesSpec new)
addFile: 'OmniBrowserVersionMap-dkh.2';
addRepository: 'http://seaside.gemstone.com/ss/test';
yourself);
yourself

we can arrange for version '0.442' of the 'dev tools' group from OBVersionMap to be loaded only when the OBNode class is missing.

This technique can avoid a raft of "is this version close enough" troubles.

Dale

stephane ducasse

unread,
May 27, 2009, 5:05:00 PM5/27/09
to montice...@googlegroups.com
just a thought I got when reading your mail.
I think that this important to pay attention

because if you got that road you lose the declarative aspects of a
dependency declaration.
In particular it means that it will be more difficult to build tools
that analysis dependency and the rest.

Bergel, Alexandre

unread,
May 27, 2009, 5:11:08 PM5/27/09
to montice...@googlegroups.com
Stef is right. A kind of repository on which one can query is
important. This will probably come at some point.

Cheers,
Alexandre
--
_,.;:~^~:;._,.;:~^~:;._,.;:~^~:;._,.;:~^~:;._,.;:
Alexandre Bergel http://www.bergel.eu
^~:;._,.;:~^~:;._,.;:~^~:;._,.;:~^~:;._,.;:~^~:;.





Dale Henrichs

unread,
May 27, 2009, 6:16:11 PM5/27/09
to montice...@googlegroups.com
Stef,

Just to clarify. Do you object to the fact that #omnibrowser does not have a well known meaning, or do you object to the fact that #hasClassNamed: is being used?

In particular in the followon example I use #seaside29, #seaside28, and #noSeaside. Are those questionable as well?

At one level, I understand that allowing for analysis is a very useful thing ... and in this example there is an OmniBrowser dependency defined, so dependencies can be inferred, what's not clear is how the dependency is triggered.

I talked to a ruby guy last night - I gave a quick overview of Metacello at the pdx ST users group meeting - and I asked if there were things that were problematic in RubyGems and one thing he mentioned that folks are finding that "there isn't enough information in a version string for making dependency decisions". So there seems to be a pragmatic advantage to being able to make a decision based on "what is in the image."

In the end, I think that it is a point well-taken. Pragmatism should be applied in the field when faced with making it work and shouldn't be used as an excuse to stop thinking about the right way to express it.

Dale

stephane ducasse

unread,
May 28, 2009, 2:08:40 AM5/28/09
to montice...@googlegroups.com
I have the impression that you can have data that describes a
situation. Then you can have like in gems a kind of little
language (<= 3.0)... but my point is that if you have a fixed and more
declarative language then it will be easier after to
build tools.
When I looked at Sake (but I may be wrong) I was a bit worried tha
this is plain smalltalk because you have waht you get a
full dynamic language.

Stef

Dale Henrichs

unread,
May 28, 2009, 12:55:57 PM5/28/09
to montice...@googlegroups.com

----- "stephane ducasse" <stephane...@gmail.com> wrote:

| I have the impression that you can have data that describes a
| situation. Then you can have like in gems a kind of little
| language (<= 3.0)... but my point is that if you have a fixed and more
|
| declarative language then it will be easier after to
| build tools.
| When I looked at Sake (but I may be wrong) I was a bit worried tha
| this is plain smalltalk because you have waht you get a
| full dynamic language.

Okay, this makes sense. I have started looking at RubyGems[1] and they have a set of version operators that I will support (thanks for the prodding). There needs to be a way to specify a dependency that is stricter than 'it is loaded' and looser than 'only this version'. Version numbers by themselves don't provide enough information by themselves but relational operators on versions will be a good start.

Dale

[1] http://rubygems.org/

Reply all
Reply to author
Forward
0 new messages