Hi.
I think at this point the discussion is mostly academic, since there are no plans for the code generator to support such incomplete models.
Certainly you would be in a better position to judge the practical value of incomplete models as I have described. To me there may be some advantages, but they may be indeed more theoretical advantages than practical.
As you point out, you could always use, for example, empty base classes and use them in place of holes. Refinement could be achieved by subclassing. The advantage of the holes is perhaps that they may give the user a bit more free-hand, in the sense that the syntax of the extended language (i.e. the language with holes) allows for more terms/models and might be less restrictive. But I agree that in our context this is a rather minor advantage, and we don't know if that would translate to real practical value over using empty base classes.
I do see a potentially better advantage of using this approach with my fourth type of generation (higher-order generator that produces generators), as an approach to software product lines, and redefinition over "model weaving". I might be getting this wrong (and feel free to point it out), but I think of model weaving as analogous to aspect-oriented programming, where you inject code over multiple places in a program. I assume that in model weaving you would be injecting model elements over a cross-section of a model, isn't that right? Now, AOP can be very useful, but it can also be a nightmare, and the reason is that if you inject aspects which are side-effect-free, then there is no problem, but if the aspects have side-effects, they can result in methods/capsules/components which violate their contract and in that case the developer cannot know by looking only at the method/component/capsule alone or with immediate context what its behaviour is. The developer has to take into consideration all possible aspects that may be injected, which are defined elsewhere. This breaks compositionality, which is analogous to breaking referential transparency in programming languages. This makes reasoning about behaviour much more difficult, as such reasoning becomes non-local.
Now, in the context of this discussion, and if I understand you correctly, one could use a form of model weaving as a means of redefinition. I agree that that approach is reasonable and you could do redefinition that way. But I'm a bit weary of weaving for the reasoned I outlined above: if is difficult to figure out what is being weaved into a given component, which makes predicting its behaviour difficult. I think that using holes or empty base classes may lead to models that are easier to understand. For example, if you have
capsule A
{
port i : P;
part x : B;
behaviour { ... }
}
and you use some for of weaving, then by looking only at the model element you won't have a complete picture of its structure and behaviour, as you do not know what elements are going to be weaved in, or where. This can be quite difficult to debug later on. On the other hand, if you have explicit holes:
capsule A
{
port i : P;
part x : B;
<X>
behaviour { ... <Y> ... }
}
then you know that something is going to be "injected" and you know where. Then the refinement operation will have the information of what is injected where. Of course, you could also use empty base classes as you point out.
Having said that, I don't think that weaving or AOP are necessarily bad. After all, they where introduced for a reason: separation of concerns. I think there is some sort of trade-off between modularity achieved by weaving and the ability to reason compositionally about a system. Perhaps there is some happy middle, but as I said at the beginning, this is more of an academic question at this point.
Having said that, if you have ideas about weaving to include in our generator, let me know!