-
Notifications
You must be signed in to change notification settings - Fork 6
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
Poolable TypeScript refactoring #103
Comments
@zepumph would you be able to review or discuss? If it looks good, I'd like to convert more things over (since this was the blocking pattern for Vector2). Also, proper TS of Action and Emitter seem like the most helpful thing next. |
I think we should really take into account https://github.com/phetsims/phet-io/issues/1543. We were going to totally refactor those two classes, but I haven't had time to do it. |
I don't like how we have to typecast the options arg. I don't think we should need to do this, but I can't understand what's different about this usage of optionize that it doesn't think that defaultArguments has been filled in. My best guess is the |
I also tried this, but it didn't really work.
|
Maybe you can get farther than I did with my example, but I was running into problems trying to duplicate the issue in wilder: Index: js/wilder/model/WilderOptionsPatterns.ts
IDEA additional info:
Subsystem: com.intellij.openapi.diff.impl.patch.CharsetEP
<+>UTF-8
===================================================================
diff --git a/js/wilder/model/WilderOptionsPatterns.ts b/js/wilder/model/WilderOptionsPatterns.ts
--- a/js/wilder/model/WilderOptionsPatterns.ts (revision 2c0da78c87c3bd78b4556135e05f3ed10ec136c8)
+++ b/js/wilder/model/WilderOptionsPatterns.ts (date 1644440768593)
@@ -59,6 +59,7 @@
* @author Michael Kauzmann (PhET Interactive Simulations)
*/
+import Constructor from '../../../../phet-core/js/Constructor.js';
import optionize from '../../../../phet-core/js/optionize.js';
import { Defaults } from '../../../../phet-core/js/optionize.js';
import wilder from '../../wilder.js';
@@ -318,18 +319,22 @@
type WrapTypeOptions<T> = {
favoriteGeneric?: MyGeneric<T>
+
+ defaultArguments?: ConstructorParameters<T>
};
-class WrapType<T> {
+class WrapType<T extends Constructor> {
favoriteGeneric: MyGeneric<T>;
constructor( providedOptions?: WrapTypeOptions<T> ) {
const options = optionize<WrapTypeOptions<T>, WrapTypeOptions<T>>( {
- favoriteGeneric: new MyGeneric<T>()
+ favoriteGeneric: new MyGeneric<T>(),
+ defaultArguments: [] as unknown as ConstructorParameters<T>
}, providedOptions );
this.favoriteGeneric = options.favoriteGeneric;
+ this.x = options.defaultArguments;
}
getFavoriteItemProperty(): MyGeneric<T> {
@@ -339,10 +344,10 @@
console.log( new WrapType() );
console.log( new WrapType( {
- favoriteGeneric: new MyGeneric<boolean>( true )
+ favoriteGeneric: new MyGeneric<MyItem>( new MyItem() )
} ) );
console.log( new WrapType( {
- favoriteGeneric: new MyGeneric<boolean>()
+ favoriteGeneric: new MyGeneric<MyItem>()
} ) );
////////////////////////////////////////////////////////////////////////////////////////////////
|
This is blocking progress on Function Builder redeploy in phetsims/function-builder#139. |
@jonathanolson ping me if you would like to pair. I'm happy to spend some time here. |
@jonathanolson and I were able to discuss a new Poolable pattern on Monday. @jonathanolson committed it and I believe is feeling pretty good about it. @jonathanolson, does this still block publication? Can this issue be closed? |
Added Pool.ts above. It gets rid of the mixin handling for pooling. This seems like the best pattern, and the IDE can detect createFromPool parameter names. It's not too much boilerplate and seems to simplify things. It also works just fine with abstract supertypes. See SVGLinearGradient for an example usage, it's basically:
freeToPool() {
SVGLinearGradient.pool.freeToPool( this );
}
static pool = new Pool( SVGLinearGradient ); where options can be added to the Pool constructor as needed. Then it's Thoughts @zepumph? |
I wrote this line at the end of SVGLinearGradient:
And it errored with:
Really great stuff! I love it. I would argue that this is less boilerplate than the javascript mixin. Anything else for this issue? |
I believe the commit above handles most issues brought up in #103 (comment).
Can I take that as a compliment?
Most of the effort in the typing is to make sure we get proper types for pool methods, to prevent errors in use of pooled types. The JS parts are mostly just in creating objects and partly performance. Mostly for usability. |
You don't want to have to know an object's concrete type in order to free it to its pool. A motivating example is in RichText, where you could have children of various different types of poolable objects (RichTextLeaf, RichTextElement, RichTextLink). You want to be able to call Since the object's only action within a pool is to free it TO that pool, it doesn't promote other things. Modifying things about pools without knowing what pool you are dealing with seems... inadvisable.
Would that mean removing |
Review continued...
public freeToPool(): void {
RichTextLeaf.pool.freeToPool( this );
}
public static readonly pool = new Pool( RichTextLeaf ); It seems that all usages of public constructor( type: T, providedOptions?: PoolableOptions<T, Params> ) {
const options = optionize<PoolableOptions<T, Params>, PoolableOptions<T, Params>>()( {
defaultArguments: [] as unknown as Params,
initialize: ( type.prototype as unknown as { initialize: PoolableInitializer<T, Params> } ).initialize,
maxSize: 100,
initialSize: 0,
useDefaultConstruction: false
}, providedOptions );
...
this.partialConstructor = Function.prototype.bind.bind( type, type ); I still don't see how
|
I agree it doesn't add type information. I'm a bit confused what you mean here. |
That is very true. It seems insufficiently documented. It seems possible (but very difficult, probably at least 8 tricky typescript lines and a ts-ignore because optionize doesn't handle this pattern) to type this nicely. The trick is "if you don't provide an initialize option, you HAVE to provide a type with initialize, OTHERWISE there is no requirement". I'm prone to improved documentation and assertions, instead of adding a lot of type system complexity to handle that case.
So, would more documentation help? |
Yes. @jonathanolson I think improved documentation would help since it does seem like trying to handle this through typescript would become overly complex. I also wonder if adding an assertion could be helpful?
|
We are closing this as completed and opening a new issue to convert PDOMinstance.ts to using the new Pool phetsims/scenery#1543, as well as js => ts conversion tracked in these issues: |
Reopening because there is a TODO marked for this issue. |
I've finally got Poolable in a state where it can work with seemingly all of the constraints. I'll collect commits here and ask for a review.
The text was updated successfully, but these errors were encountered: