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

Click handler refactoring proposal #274

Merged
merged 15 commits into from
Feb 27, 2017

Conversation

stefanbuck
Copy link
Member

@stefanbuck stefanbuck commented Feb 1, 2017

Once @josephfrazier suggested to combine the plugin click handler (aka resolver) with the actual plugin. At this time, I was assuming that we can benefit from reusing those resolver from one plugin in others. Now, after a couple of months of adding more and more languages, it shows up that only a small portion ( git-url, relative-file and live-resolver-query) of resolver are reused.

Exemplary I refactored the Docker and Python plugin to show you how it could work. I'll polish the PR if you agree with the solution. I'm looking forward to your feedback.

Please, review the PR with ?w=1 to ignore whitespace changes.

TODO

  • Refactor Docker plugin
  • Refactor Python plugin
  • Refactor Rust plugin
  • Refactor Vim plugin
  • Refactor Ruby plugin
  • Refactor Go plugin
  • Refactor .Net Core plugin
  • Refactor Rubygems plugin
  • Refactor Homebrew plugin
  • Refactor Composer plugin
  • Refactor JavaScript plugin
  • Refactor TypeScript plugin
  • Refactor npm plugin
  • Refactor Bower plugin

@josephfrazier
Copy link
Member

This is a big one, so I'll try to take a look at it over the weekend. Thanks for the heads-up about the whitespace changes.

@stefanbuck
Copy link
Member Author

No rush 😉

Copy link
Member

@josephfrazier josephfrazier left a comment

Choose a reason for hiding this comment

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

Ok, I got a chance to review this. I really like the changes overall! It's exciting to see my proposal in #86 taking shape.

I added a handful of small comments about variable names and function signatures, but this looks good otherwise 👍

PS: It turns out that using ?w=1 to ignore whitespace changes makes it impossible to add inline comments (isaacs/github#394). That didn't cause much trouble though, as I had already read the code without the whitespace changes, before I tried to start adding comments.

};
});
}
const pluginName = dataAttr._pluginName;
Copy link
Member

Choose a reason for hiding this comment

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

I think we should rename _pluginName to simply pluginName, since there's no previously existing pluginName variable that it would be shadowing.

const dataAttr = {};
function buildDataAttr(_pluginName, data, match) {
const dataAttr = {
_pluginName,
Copy link
Member

Choose a reason for hiding this comment

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

EDIT: See this comment first: https://github.com/OctoLinker/browser-extension/pull/274/files#r99663118

If you agree with my comment at https://github.com/OctoLinker/browser-extension/pull/274/files#r99657441, we should also change _pluginName to pluginName on this line (and in the function definition).

});
}
const pluginName = dataAttr._pluginName;
const resolver = pluginManager.getClickHandler(pluginName);
Copy link
Member

Choose a reason for hiding this comment

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

I think we should rename getClickHandler to getResolver, since that more accurately describes what the return value does (and matches the variable name used here).

this._plugins = buildPluginCache(plugins);
}

getClickHandler(pluginName) {
Copy link
Member

Choose a reason for hiding this comment

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

If you agree with my comment at https://github.com/OctoLinker/browser-extension/pull/274/files#r99658228, we should also change getClickHandler to getResolver here.

return;
}

return plugin.clickHandler;
Copy link
Member

Choose a reason for hiding this comment

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

In the spirit of https://github.com/OctoLinker/browser-extension/pull/274/files#r99658228, I think clickHandler should instead be resolve on this line and in the previous conditional.

@@ -4,13 +4,25 @@ import preset from '../../pattern-preset';

export default class Docker {

static clickHandler({ image }) {
Copy link
Member

Choose a reason for hiding this comment

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

If you agree with my comment at https://github.com/OctoLinker/browser-extension/pull/274/files#r99658736, we should also change clickHandler to resolve here.


export default class Python {

static clickHandler({ path, target }) {
Copy link
Member

Choose a reason for hiding this comment

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

If you agree with my comment at https://github.com/OctoLinker/browser-extension/pull/274/files#r99658736, we should also change clickHandler to resolve here.

getPattern() {
return preset('Docker');
}

parseBlob(blob) {
insertLink(blob.el, DOCKER_FROM, {
resolver: 'dockerImage',
insertLink(this, blob.el, DOCKER_FROM, {
Copy link
Member

Choose a reason for hiding this comment

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

Instead of passing the plugin as the first argument to insertLink, what if we just put it into the object literal, alongside image:

insertLink(blob.el, DOCKER_FROM, {
  pluginName: this.constructor.name,
  image: '$1',
});

This way, insertLink won't have to pass an extra argument to replace and buildDataAttr at all. Note that doing this would invalidate my comment at https://github.com/OctoLinker/browser-extension/pull/274/files#r99657840, since the extra argument will no longer be present.

Copy link
Member Author

@stefanbuck stefanbuck Feb 6, 2017

Choose a reason for hiding this comment

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

The idea of passing the plugin to insertLink was to avoid duplication of pluginName: this.constructor.name across all plugins. To avoid conflicts with other prop key names passed to insertLink the name is prefixed with an underscore.

Maybe it's not the best idea, since it hides the actual behaviour and makes it just more complicated. Thanks for pointing me in the right direction.

That's why I believe and love code reviews 👍

Copy link
Member

Choose a reason for hiding this comment

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

Yeah, I was thinking about the duplication as well, when I was writing the comment. It's not ideal, but I think it's worth the gains in clarity that putting it in the map gives.

If you'd like, you could instead pass plugin: this to insertLink, and insertLink could delete the plugin key and add a pluginName key, to avoid duplicating .constructor.name, but I'm not sure if that's better...

I definitely agree on loving code reviews 👍

Copy link
Member Author

Choose a reason for hiding this comment

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

I went with the map solution for simplicity.

getPattern() {
return preset('Python');
}

parseBlob(blob) {
insertLink(blob.el, PYTHON_IMPORT, {
resolver: 'pythonUniversal',
insertLink(this, blob.el, PYTHON_IMPORT, {
Copy link
Member

Choose a reason for hiding this comment

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

@stefanbuck
Copy link
Member Author

Thanks for the great feedback. I'll follow up on your naming suggestions.

Regarding the refactoring. Do you think it makes sense to open a refactor PR for every single plugin? If we do that, we have to make it backwards compatible in order to keep the other plugins working. If you agree, I would like to open one big PR where every plugin refactoring is a commit. This should make it easier to review.

@josephfrazier
Copy link
Member

I think it'd be much better to have a single PR with one plugin per commit, as you've described. Making separate PRs doesn't seem like it's worth the effort of maintaining backwards-compatibility. I look forward to seeing the updates!

@stefanbuck stefanbuck force-pushed the clickhandler-refactoring branch 5 times, most recently from 141eee7 to 04b9ae2 Compare February 7, 2017 23:56
@@ -1,38 +1,38 @@
import assert from 'assert';
import dockerImage from '../../lib/resolver/docker-image.js';
import dockerImage from '../../lib/plugins/docker';
Copy link
Member Author

Choose a reason for hiding this comment

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

For simplicity and keeping the PR small as possible, I just fixed the broken tests. I'll polish all plugin tests in a separate PR.

@stefanbuck stefanbuck force-pushed the clickhandler-refactoring branch from 04b9ae2 to ee99bba Compare February 9, 2017 23:45
@stefanbuck stefanbuck force-pushed the clickhandler-refactoring branch 2 times, most recently from ea15c73 to e24c1dd Compare February 21, 2017 23:40
gitUrl({ target }),
githubShorthand({ target }),
];
}
Copy link
Member Author

Choose a reason for hiding this comment

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

@josephfrazier what do you think about handling the different resolver types in one handler? It feels a bit inconvenient to me. In the old implementation this case was handled in a better way.

One possible option would be to split the plugin by features. In this case one for linking the dependencies and another which is responsible for linking the main field. I'm not sure if this makes thing easier or more complicated.

Copy link
Member

Choose a reason for hiding this comment

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

Are you talking about the calls to JavaScriptPlugin.resolve, liveResolverQuery, gitUrl, and githubShorthand being made explicitly, rather than implicitly like they are here and here? That doesn't really seem like a problem to me, but perhaps I'm misunderstanding the question. Splitting the Bower plugin into multiple other plugins sounds like it would just make things more complicated, especially if it's done as part of this refactor, rather than as a separate change.

Copy link
Member Author

Choose a reason for hiding this comment

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

I'm talking about the if statements in the resolve function. In my current implementation, the type attributes define which resolver is used. Without knowing how the click-handler works, I would assume that every insertLink can have his own click handler. What do you think? Maybe I'm over-thinking it.

Copy link
Member Author

Choose a reason for hiding this comment

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

Let's ignore this for now. It's not really important

Copy link
Member

Choose a reason for hiding this comment

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

Yeah, I think we can worry about that later if needed :)

@stefanbuck
Copy link
Member Author

stefanbuck commented Feb 21, 2017

I'm almost complete with this one. There is one outstanding question regarding the resolve handler function. Besides that I'm almost through. I'll do some minor improvements + the remaining code review comments later this week.

@stefanbuck stefanbuck force-pushed the clickhandler-refactoring branch 4 times, most recently from 63a85f7 to eb7b6c3 Compare February 25, 2017 09:27
@stefanbuck stefanbuck force-pushed the clickhandler-refactoring branch from 7d3ef18 to eb7b6c3 Compare February 26, 2017 21:28
@stefanbuck
Copy link
Member Author

stefanbuck commented Feb 26, 2017

@josephfrazier can you help with this? Disabling the cache didn't helped.

Downloading googlechrome 64 bit
  from 'https://dl.google.com/tag/s/dl/chrome/install/googlechromestandaloneenterprise64.msi'
Progress: 100% - Completed download of C:\Users\appveyor\AppData\Local\Temp\1\chocolatey\GoogleChrome\56.0.2924.87\googlechromestandaloneenterprise64.msi (48.26 MB).
Download of googlechromestandaloneenterprise64.msi (48.26 MB) completed.
Error - hashes do not match. Actual value was '1450DE87F0289CE725DF1C138BBA2666304FB94BF4476B03C06D058C999D4805'.
ERROR: Checksum for 'C:\Users\appveyor\AppData\Local\Temp\1\chocolatey\GoogleChrome\56.0.2924.87\googlechromestandaloneenterprise64.msi' did not meet 'c47ff551ff8b251268905cd87fb299959e6bcb3640a3e60085a3a7dbf176845f' for checksum type 'sha256'. Consider passing --ignore-checksums if necessary.
The install of googlechrome was NOT successful.
Error while running 'C:\ProgramData\chocolatey\lib\GoogleChrome\tools\chocolateyInstall.ps1'.
 See log for details.
Chocolatey installed 0/1 packages. 1 packages failed.
 See the log for details (C:\ProgramData\chocolatey\logs\chocolatey.log).
Failures
 - googlechrome (exited -1) - Error while running 'C:\ProgramData\chocolatey\lib\GoogleChrome\tools\chocolateyInstall.ps1'.
 See log for details.
Did you know the proceeds of Pro (and some proceeds from other 

@josephfrazier
Copy link
Member

Hmm, that's a weird one. I just searched for the error and it looks like other people are seeing it too: https://chocolatey.org/packages/GoogleChrome#comment-3171878283

I don't really know why this would be happening, but it seems fine to add --ignore-checksums to the install command, considering it's being downloaded over HTTPS from Google.

@stefanbuck stefanbuck force-pushed the clickhandler-refactoring branch 2 times, most recently from 705e742 to 67a2726 Compare February 27, 2017 06:45
@stefanbuck
Copy link
Member Author

@josephfrazier can I merge it by myself or is there anything left from your side?

@josephfrazier
Copy link
Member

This looks good to me. Excellent work on this! I'll let you do the honors of merging 👍

@stefanbuck stefanbuck merged commit 713cb22 into OctoLinker:master Feb 27, 2017
@stefanbuck
Copy link
Member Author

😄 🎉

@stefanbuck stefanbuck deleted the clickhandler-refactoring branch February 27, 2017 16:55
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Development

Successfully merging this pull request may close these issues.

2 participants