phetsims / pendulum-lab

"Pendulum Lab" is an educational simulation in HTML5, by PhET Interactive Simulations.
GNU General Public License v3.0
4 stars 10 forks source link

Node options should be passed to Node.call() when possible #68

Closed aaronsamuel137 closed 9 years ago

aaronsamuel137 commented 9 years ago

During code review #56 I noticed this code in PeriodTraceNode

    Node.call( this, options );

    this.rotation = Math.PI / 2;

It seems like the usual PhET convention would be to pass rotation in as one of the Node options like so:

    Node.call( this, _.extend( {
      rotation: Math.PI / 2
    }, options ) );

This way it is more clear that rotation is a Node a option and not a private attribute. Is there any reason why this isn't being done? Will you either change this or add some documentation. Thanks.

aaronsamuel137 commented 9 years ago

A similar pattern occurs in PendulumLabView:

    var returnButtonNode = new ReturnButtonNode( {
      listener: pendulumLabModel.returnHandler.bind( pendulumLabModel )
    } );
    returnButtonNode.centerX = resetAllButton.bounds.minX - 75;
    returnButtonNode.centerY = height - SCREEN_PADDING.BOTTOM - 5;
aaronsamuel137 commented 9 years ago

And in StopwatchNode:

    Timer.call( this, stopwatch.elapsedTimeProperty, stopwatch.isRunningProperty );

    this.centerX = toolsControlPanelNodeBounds.maxX - this.width / 2;
    this.centerY = toolsControlPanelNodeBounds.minY - this.height / 2 - 5;
andrey-zelenkov commented 9 years ago

Added using of Node.call in PeriodTraceNode and PendulumLabView. Center of StopwatchNode depend on Times's size and can be set only after creating of Timer. Reassign to @aaronsamuel137 for verification.

pixelzoom commented 9 years ago

@aaronsamuel137 Actually, the more common pattern is:

function MyNode( ..., options ) {

  options = _.extend( {
     // define options and their default values
  }, options );

  Node.call( this );

  // add children, do other things

  this.mutate( options );
}

If you pass options to Node.call before children are added, transformation-related options will cause an assertion error (something like "suspicious matrix operation") because the bounds of a Node are Bounds2.NOTHING by default. Doing this.mutate( options ) as the final step in the constructor ensures that the node's portion of the scene graph is defined before applying options.

aaronsamuel137 commented 9 years ago

@pixelzoom, I'm aware of that pattern, but in these cases there was no need to call this.mutate( options ).

Would you suggest using that pattern everywhere for consistency even when it isn't necessary?

pixelzoom commented 9 years ago

No need to use that pattern everywhere. And I didn't look at the specific case is question here. But the example you gave was for Node, and Node.call( this, options ) is highly likely to cause an assertion failure. So for subtypes of Node, it's highly recommended to use the this.mutate pattern.

aaronsamuel137 commented 9 years ago

OK thanks for pointing that out and clarifying.

aaronsamuel137 commented 9 years ago

This looks good to me as far as these specific instances are concerned. Closing