Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Anti-pattern for defining static readonly class properties. #278

Closed
pixelzoom opened this issue Oct 23, 2022 · 14 comments
Closed

Anti-pattern for defining static readonly class properties. #278

pixelzoom opened this issue Oct 23, 2022 · 14 comments

Comments

@pixelzoom
Copy link
Contributor

I'm seeing a pattern of definiting static class properties that is concerning. It results in those constants being writeable when they should be readonly.

For example, here's Vector2.ts:

export default class Vector2 implements TPoolable {
...
  public static ZERO: Vector2;
  public static X_UNIT: Vector2;
  public static Y_UNIT: Vector2
  public static Vector2IO: IOType;
}

Vector2.ZERO = assert ? new ImmutableVector2( 0, 0 ) : new Vector2( 0, 0 );
Vector2.X_UNIT = assert ? new ImmutableVector2( 1, 0 ) : new Vector2( 1, 0 );
Vector2.Y_UNIT = assert ? new ImmutableVector2( 0, 1 ) : new Vector2( 0, 1 );

Vector2.Vector2IO = new IOType<Vector2, Vector2StateObject>( 'Vector2IO', {
  ...
} );

All of the static properties should be static readonly. And they should be instantiated inside the class definition, not outside the class definition. Like this:

export default class Vector2 implements TPoolable {
...
  public static ZERO = assert ? new ImmutableVector2( 0, 0 ) : new Vector2( 0, 0 );
  public static X_UNIT = assert ? new ImmutableVector2( 1, 0 ) : new Vector2( 1, 0 );
  public static Y_UNIT = assert ? new ImmutableVector2( 0, 1 ) : new Vector2( 0, 1 );
  public static Vector2IO = new IOType<Vector2, Vector2StateObject>( 'Vector2IO', {
    ...
  } );
}

A couple of things for discussion at developer meeting:

(1) PSA and recommendation not to use this pattern. Statics that are read-only should have the readonly modifier.

(2) Can we write a lint rule to prevent this, and identify all of the existing cases?

@pixelzoom
Copy link
Contributor Author

This problem is widespread. For example, looking only at IOType definitions:

@samreid I see this anti-pattern throughout cck-common:

  • CircuitElement.CircuitElementIO
  • Resistor.ResistorIO
  • Vertex.VertexIO

@jonathanolson in density-buoyancy-common and gravity-and-orbits:

  • Cuboid.CuboidIO
  • Gravity.GravityIO
  • Mass.MassIO
  • Material.MaterialIO
  • Body.BodyIO

@jbphet in greenhouse-effect, you're instantiating these inside the class definition, but missing readonly modifier:

  • public static EMEnergyPacketIO
  • all public static in Photon.ts
  • public static WaveCreationSpecIO
  • public static EMWaveSourceIO
  • public static WaveIO

@marlitas in mean-share-and-balance:

  • Pipe.PipeIO

@jonathanolson in scenery:

  • Input.InputIO
  • Pointer.PointerIO

@jonathanolson
Copy link
Contributor

Tried out the Vector2 example (since it was not ported that way because of ImmutableVector2), and it fails:

image

I don't see a way of handling this with other ways easily, can you recommend a pattern for use at this site other than what's being done?

@jonathanolson
Copy link
Contributor

Avoiding this pattern for most of the above cases however seems quite helpful.

marlitas added a commit to phetsims/mean-share-and-balance that referenced this issue Oct 23, 2022
@marlitas
Copy link
Contributor

marlitas commented Oct 23, 2022

Addressed the MSaB occurrence. This seems useful and writing a lint rule is a good idea.

pixelzoom added a commit to phetsims/mean-share-and-balance that referenced this issue Oct 24, 2022
@pixelzoom
Copy link
Contributor Author

@marlitas Static constants should not be assigned in the constructor, because the constructor is called every time that new Pipe is called. See the commit above for the correct way to define a static constant. Let me know if you have any questions.

@samreid samreid self-assigned this Oct 24, 2022
@samreid
Copy link
Member

samreid commented Oct 24, 2022

I agree these are antipatterns but also wanted to point out the overlap in #275 in which we may (as a long term solution) combine IOTypes with the core types.

@samreid samreid removed their assignment Oct 24, 2022
@pixelzoom
Copy link
Contributor Author

Yes, there's indeed overlap with #275. But I want to emphazied that, while the examples I've pointed to involve IOTypes, the antipattern applies to all statics, not just IOTypes. Do a search for "public static" and you'll find many examples.

marlitas added a commit to phetsims/mean-share-and-balance that referenced this issue Oct 24, 2022
@jbphet
Copy link
Contributor

jbphet commented Oct 24, 2022

Thanks for pointing this out @pixelzoom. I made changes in quite a few places in greenhouse-effect, beyond the list shown above. @marlitas - I agree that a lint rule for this would be helpful.

jbphet referenced this issue in phetsims/greenhouse-effect Oct 24, 2022
@jessegreenberg
Copy link
Contributor

jessegreenberg commented Oct 27, 2022

Here is the example AST, it should be easy to make a lint rule to flag when readonly is missing: https://typescript-eslint.io/play/#ts=4.8.4&sourceType=module&showAST=es&code=MYGwhgzhAECyCeBhcVoG8CwAoa0AOArgEYgCWw0EALmFedAE4CmYAJgPYB2I80AKgFEAynwD6fABIBJAHIBxaAF5oAckEiVAbmwBfIA

Might also be easy to add an auto-fix.

EDIT: Well... easy to find these in the AST but not easy to determine the intent, lots of public static should probably still be writable.

@samreid
Copy link
Member

samreid commented Nov 17, 2022

Dev meeting Nov 17 2022.

We agreed that making public static class properties readonly is best. Just something that needs to be cleaned up.

@zepumph: I see 262 usages where this pattern is happening. Maybe half of them can be fixed. So that is maybe 2 hours of work to do it all.
@AgustinVallejo: I'm happy to help on this.
@kathy-phet: Can @pixelzoom and @AgustinVallejo pair together for a "kick-off" meeting, then @AgustinVallejo take it from there?

@pixelzoom & @AgustinVallejo: Great!

Here is a regex from @zepumph that may help static .*:.*;

@samreid samreid assigned pixelzoom and AgustinVallejo and unassigned marlitas Nov 17, 2022
@veillette veillette reopened this Nov 17, 2022
@pixelzoom
Copy link
Contributor Author

@AgustinVallejo and I met about this after today's dev meeting. He'll use the regex static .*:.*; to identify potential places to add readonly. For any that prove to be problematic (like Vector2), he'll note them, and he and I will review.

AgustinVallejo added a commit to phetsims/density-buoyancy-common that referenced this issue Nov 22, 2022
AgustinVallejo added a commit to phetsims/center-and-variability that referenced this issue Nov 22, 2022
AgustinVallejo added a commit to phetsims/counting-common that referenced this issue Nov 22, 2022
AgustinVallejo added a commit to phetsims/build-a-nucleus that referenced this issue Nov 22, 2022
AgustinVallejo added a commit to phetsims/bending-light that referenced this issue Nov 22, 2022
AgustinVallejo added a commit to phetsims/axon that referenced this issue Dec 1, 2022
pixelzoom added a commit to phetsims/circuit-construction-kit-common that referenced this issue Dec 1, 2022
pixelzoom added a commit to phetsims/density-buoyancy-common that referenced this issue Dec 1, 2022
pixelzoom added a commit to phetsims/circuit-construction-kit-common that referenced this issue Dec 1, 2022
pixelzoom added a commit to phetsims/density-buoyancy-common that referenced this issue Dec 1, 2022
pixelzoom added a commit to phetsims/counting-common that referenced this issue Dec 1, 2022
pixelzoom added a commit to phetsims/greenhouse-effect that referenced this issue Dec 1, 2022
pixelzoom added a commit to phetsims/joist that referenced this issue Dec 1, 2022
pixelzoom added a commit to phetsims/kite that referenced this issue Dec 1, 2022
pixelzoom added a commit to phetsims/models-of-the-hydrogen-atom that referenced this issue Dec 1, 2022
pixelzoom added a commit to phetsims/my-solar-system that referenced this issue Dec 1, 2022
pixelzoom added a commit to phetsims/number-compare that referenced this issue Dec 1, 2022
pixelzoom added a commit to phetsims/number-play that referenced this issue Dec 1, 2022
pixelzoom added a commit to phetsims/quadrilateral that referenced this issue Dec 1, 2022
pixelzoom added a commit to phetsims/ratio-and-proportion that referenced this issue Dec 1, 2022
pixelzoom added a commit to phetsims/scenery-phet that referenced this issue Dec 1, 2022
pixelzoom added a commit to phetsims/sun that referenced this issue Dec 1, 2022
pixelzoom added a commit to phetsims/tambo that referenced this issue Dec 1, 2022
pixelzoom added a commit to phetsims/utterance-queue that referenced this issue Dec 1, 2022
pixelzoom added a commit to phetsims/wilder that referenced this issue Dec 1, 2022
pixelzoom added a commit to phetsims/tappi that referenced this issue Dec 1, 2022
pixelzoom added a commit to phetsims/circuit-construction-kit-common that referenced this issue Dec 1, 2022
pixelzoom added a commit to phetsims/dot that referenced this issue Dec 1, 2022
@pixelzoom
Copy link
Contributor Author

pixelzoom commented Dec 1, 2022

In the above commits, I addressed a bunch more cases. There are still some cases that have not been addressed (as indicated in #278 (comment)) because they are problematic. And there are some cases in sun and scenery that are just a little too much work to untangle and test. But I don't feel like we need to address every case for this issue (diminishing returns...), and I feel like we're at a good stopping point. @AgustinVallejo do you agree? If so, feel free to close this issue. If not, what else should we do?

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

No branches or pull requests

8 participants