On 6/24/16 6:28 AM, Norbert Hartl wrote:
I have a seaside project that will be installed in a typical fashion headless 
on a server somewhere on the net. The project is in its final stage so I 
started to care about the size of the image. Or better: The size of the image 
is not my main concern but the number of packages installed. The less packages 
you load the better it is, it is that simple.
This time I encountered a problem that I often see but this particular one 
explains in a very good way that how we use metacello can be improved.

In my project I load only Seaside-Core. This has the advantage of loading far 
less packages and I don't have the need to remove a bunch of registered web 
applications that registered themselves when being loaded.
I make use of a bootstrap template bought somewhere on the net. I use magritte 
a lot so I was happy to see that there is a package called BootstrapMagritte. 
The package extends some magritte ui classes and overwrites some methods to add 
specific classes to HTML tags. Basically not very much code.
What happended after I added the package as a dependency to my own project you 
can see here in the load directive of metacello

linear load :
        explicit load : 0.2.3 [ConfigurationOfBootstrapMagritte]
        linear load : 0.2.3 [ConfigurationOfBootstrapMagritte]
                linear load : 3.5.0 [ConfigurationOfMagritte3]
                        linear load : 1.1.0 
[ConfigurationOfMagritteGlamourForPharo40]
                                load : 
Glamour-Presentations.issue_1126-SeanDeNigris.178
                                load : 
Glamour-Morphic-Renderer.issue_1126-SeanDeNigris.325
                        explicit load : 3.1.5 [ConfigurationOfSeaside3]
                        linear load : 3.1.5 [ConfigurationOfSeaside3]
                                explicit load : 0.26 [ConfigurationOfParasol]
                                linear load : 0.26 [ConfigurationOfParasol]
                                        linear load : 3.2.0 
[ConfigurationOfSeaside3]
                                load : 
Seaside-Tests-REST-Core-EstebanMaringolo.34

This is wrong in so many ways. I load a little extensions to my web application 
and end up loading _all_ of seaside which loads beach parasol (a ui testing 
framework), _all_ of magritte which in turn loads glamour packages (a ui 
toolkit). So at this point I think WTF?

Why does this happen? Because the "default" group in many projects contains all of the 
packages and dependencies of the project. I thought at first this is wrong but in the meantime I 
think it is right. Whenever a configuration is loaded without additional parameters the 
"default" group gets loaded. This is the best scenario for newcomers (e.g. using the 
catalog to load). They don't know better but want to see what the package has to offer. Fine, we 
should support that.

For managing projects this gets annoying really quick like you can see above. It would always load 
all dependencies and all packages of every project that your own project depends. This is a no-go. 
To circumvent this a lot of people add a "core" group to their configurations (loading 
the essential parts). This is great because in my own project I can add a dependency to a project 
and load only the "core" group. This works if the dependency chain is not very long (at 
best it works in depth 1 ;) ). As soon as a project has two interesting groups the problem gets 
worse. A good example is magritte. It is useful for describing your model as well as it contains 
useful seaside components. The moment I add a dependency from my model package to magritte seaside 
I know it is wrong. I find myself sometimes duplicating dependencies just to mitigate the effect. I 
do something like

                        project: 'Magritte3Seaside' with: [
                                spec
                                        className: #ConfigurationOfMagritte3;
                                        versionString: #'stable';
                                        loads: #('Seaside' );
                                        repository: 
'http://smalltalkhub.com/mc/Magritte/Magritte3/main/' ];
                        project: 'Magritte3Core' with: [
                                spec
                                        className: #ConfigurationOfMagritte3;
                                        versionString: #'stable';
                                        loads: #('Core' );
                                        repository: 
'http://smalltalkhub.com/mc/Magritte/Magritte3/main/' ];

and…
                        package: #'MyProject-Model-Core' with: [
                                spec requires: #( 'Magritte3Core' ). ];
                        package: #'MyProject-UI-Core' with: [
                                spec requires: #( 'Seaside3' 'Magritte3Seaside' 
'BootstrapMagritte'  ). ];


just to be able to put the right dependencies. But this way is cumbersome to do 
and not support by tools like Versionner.

The main problem to me is that the maintainer of the configuration defines the 
granularity of pieces to load forcing me to do stupid workarounds to achieve what I want. 
To me the problem is that the separation is not done properly. I think the logic of 
having loads() in the baseline and a pure string like "Magritte3Core" in the 
dependency spec is reversed. It should be

                        project: 'Magritte3' with: [
                                spec
                                        className: #ConfigurationOfMagritte3;
                                        versionString: #'stable';
                                        repository: 
'http://smalltalkhub.com/mc/Magritte/Magritte3/main/' ];

and…

                        package: #'MyProject-Model-Core' with: [
                                spec requires: #( 'Magritte3:Core' ). ];
                        package: #'MyProject-UI-Core' with: [
                                spec requires: #( 'Seaside3' 
'Magritte3:Seaside' 'BootstrapMagritte'  ). ];

Note the "Magritte3:Core" in the dependency spec. The meaning is that there is 
a dependency to Magritte3 and group Core. This way dependencies can be properly aligned. 
Or are there other way to deal with it?

What do you think?

Norbert
Norbert,

Does the following meet your needs?

                        project: 'Magritte3' with: [
                                spec
                                        className: #ConfigurationOfMagritte3;
                                        versionString: #'stable';
                                        repository: 
'http://smalltalkhub.com/mc/Magritte/Magritte3/main/' ];

                        project: 'Magritte3Seaside'
                                copyFrom: 'Magritte'
                                with: [ spec loads: #('Seaside' ) ];
                        project: 'Magritte3Core'
                                copyFrom: 'Magritte'
                                with: [ spec loads: ##('Core' ) ];


I assume the "stupid workaround" is the fact that in your example you had to specify 
Magritte twice? #project:copyFrom:with: has been around for a long time in Metacello and was 
invented to solve this particular problem ... FWIW, this feature is documented in Lesson12 of 
"Metacello Configuration Tutorial Part 2" in the Help Browser ...

Dale


Reply via email to