[Adding Laszlo-Dev, because I think this discussion deserves a wider audience.]

On 2010-04-09, at 22:00, Max Carlson wrote:

> Wouldn't basecomponent need to say:
>        <attribute name="_enabled" value="${this._compute_enabled()}" 
> setter="this._setEnabled(_enabled)"/>
> 
> Instead of:
>        <attribute name="_enabled" value="${this._compute_enabled}" 
> setter="this._setEnabled(_enabled)"/>

Indeed!  Makes me wonder how good our tests could be if they all pass with this 
severely broken!

> Instead of hacking the components, shouldn't we fix the constraint compiler 
> to deal with conditional constraints?   If not, it seems like we need some 
> syntactic sugar to declare constraints and some documentation - I'm not sure 
> how someone encountering a constraint warning would figure out how to 
> manually write a dependency method...

I can't think how this could be done automatically.  In essence, what is 
_really_ happening in components is they are installing one of two different 
constraints depending on whether or not the component is inside another 
component -- a condition which is determined at init time.  The compiler can't 
possibly figure out that the decision in the constraint needs only to be made 
once, hence it tries to generate a constraint that evaluates all the 
dependencies, all the time; which results in the dependency expression failing. 
 This constraint is working today more out of sheer luck than out of design.

I agree that writing the internal dependency method is too complex.  I think 
there are two approaches:

1) We could try to create some mechanism for dynamically installing 
constraints, so for instance, in this case, the init method would, after 
determining whether or not the component was inside another component install 
one or the other of the actual constraints.  The problem with this approach is 
that we would have to also provide a mechanism to determine when the attribute 
being constrained has not had its constraint overridden in a subclass or 
instance.  [This is a bug that was the bane of constraints for a long time, 
until we came up with the unified init-args mechanism, where _all_ initial 
values, constraints, bindings, or literals appear in a single list that can be 
merged/overridden uniformly.  So, I don't think this is really a solution.

2) We create another special tag <dependencies> that lets you easily write a 
dependency method for another method.  For example, in this case I would write:

    <dependencies name="_compute_enabled" args="">
        if (this._parentcomponent != null) {
          return [this, 'enabled', this._parentcomponent, '_enabled']
        } else {
          return [this, 'enabled'];
        }
    </dependencies>

Although you would still need to be pretty advanced to understand what your 
dependencies should be.  (I note that a lot of the hand-crafted dependency 
methods that already exist were written by looking at the default compiler 
output and then cleaning them up.)

I'm open to other suggestions, but I think we don't want our constraint system 
to just work by accident.


Reply via email to