[Laszlo-dev] For Review: Change 20100409-ptw-7 Summary: Make constraints and dependencies more debuggable and compatible

P T Withington ptw at pobox.com
Sun Apr 11 04:36:47 PDT 2010

[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'];

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.

More information about the Laszlo-dev mailing list