Skip to content

Conversation

@not-my-profile
Copy link
Contributor

No description provided.

@changeset-bot
Copy link

changeset-bot bot commented Jul 1, 2023

⚠️ No Changeset found

Latest commit: 28f8c43

Merging this PR will not cause a version bump for any packages. If these changes should not result in a new version, you're good to go. If these changes should result in a version bump, you need to add a changeset.

This PR includes no changesets

When changesets are added to this PR, you'll see the packages that this PR includes changesets for and the associated semver types

Click here to learn what changesets are, and how to add one.

Click here if you're a maintainer who wants to add a changeset to this PR

@andrewbranch
Copy link
Collaborator

If you’d like to contribute, please comment on an issue or open a new one. Thanks!

@not-my-profile
Copy link
Contributor Author

Right for changes that aren't refactors or larger changes I usually open an issue first but for smaller refactors I don't really see the point, since the changes can just as well be discussed in the PR.

I was trying to make sense of the MultiCompilerHost implementation and found the code repetitive and hard to read, so I ended up doing this refactor (which I tried to explain in the last commit message).

@andrewbranch andrewbranch reopened this Jul 8, 2023
@andrewbranch
Copy link
Collaborator

andrewbranch commented Jul 8, 2023

Sorry to jump the gun a bit on closing this. When I saw a PR with zero description I assumed there was very little chance this would be valuable. I like this over all. I’m not a huge fan of classes, and the switch from closures to classes feels a bit arbitrary. I wouldn’t unconditionally reject classes, but const that = this and .bind(this.traceCollector) make them feel not worthwhile in this case. If you’re willing to revert back to closures + POJOs, I’d be happy to take this reorganization.

The logic of the MultiCompilerHost almost only operated on one
CompilerHost plus respective CompilerOptions and caches, so it makes
sense to encapsulate this logic for one instance of these properties,
instead of requiring each of these properities to be a Record and having
to index them all the time.

The resulting code is less repetitive and more readable.
@not-my-profile
Copy link
Contributor Author

not-my-profile commented Jul 8, 2023

Thanks for taking a look at the changes. I just rebased the PR. I agree about the two ugly points you spotted, but they are not due to the switch to classes. I just fixed both of them by using arrow functions (which you apparently can also do in a class).

btw if you merge this I'd appreciate the individual commits to be preserved to get more readable diffs in the git history.

Comment on lines +202 to +207
class TraceCollector {
private traces: string[] = [];

trace = (message: string) => {
this.traces.push(message);
};
Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I honestly didn't know that you could use an arrow function like this in a class to avoid having to bind the function outside but it works.

Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Methods are declared on the class prototype so they can be shared between all instances. This is a class field, which is initialized on each instance during construction (equivalent to doing Object.defineProperty(this, "trace", ...) in the constructor). This has a perf/memory cost as compared to a true method, but of course, the cost is equivalent to every other way of accomplishing what we’re trying to accomplish here—.bind also creates a new copy of the function; it was just happening at a different time and place. There’s no way around creating a new function identity for each CompilerHost["trace"]. (As a piece of trivia, this was a common trick for React devs in the days of class components for event handlers, so you could do <button onClick={this.onClick}> instead of this.onClick.bind(this).) This still has a bit of a weird smell to me since you have to recognize which functions need this weird syntactic trick and which don’t. On the upside though, it’s a bit more efficient since at least read and clear are shared between all instances. It’s mostly a personal preference. I don’t love it but I appreciate the contribution so I’ll merge it 😛

@not-my-profile not-my-profile changed the title Refactor core Refactor MultiCompilerHost Jul 8, 2023
@andrewbranch andrewbranch merged commit 445b1f2 into arethetypeswrong:main Jul 8, 2023
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants