-
Notifications
You must be signed in to change notification settings - Fork 1.2k
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
Added a prompt asking users to enroll back in the insiders program #7484
Conversation
Codecov Report
@@ Coverage Diff @@
## master #7484 +/- ##
==========================================
+ Coverage 58.51% 58.75% +0.23%
==========================================
Files 494 494
Lines 21828 21862 +34
Branches 3499 3508 +9
==========================================
+ Hits 12773 12845 +72
+ Misses 8264 8216 -48
- Partials 791 801 +10
Continue to review full report at Codecov.
|
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Please get it reviewed by someone else as well.
I have a few concerns about:
- The structure of the tests (difficult to follow as we've tried to make it very dynamic)and some code. Again, please read my comments. Personally I'm not a big fan of trying to make tests dynamic, makes it difficult to follow (all for the benefit of code reuse in tests!)
- Some of the code seems too complicated (too many if conditions)
src/test/common/insidersBuild/insidersExtensionService.unit.test.ts
Outdated
Show resolved
Hide resolved
src/test/common/insidersBuild/insidersExtensionPrompt.unit.test.ts
Outdated
Show resolved
Hide resolved
f86303f
to
f7c8e31
Compare
f7c8e31
to
2292854
Compare
src/test/common/insidersBuild/insidersExtensionService.unit.test.ts
Outdated
Show resolved
Hide resolved
src/test/common/insidersBuild/insidersExtensionService.unit.test.ts
Outdated
Show resolved
Hide resolved
src/test/common/insidersBuild/insidersExtensionService.unit.test.ts
Outdated
Show resolved
Hide resolved
src/test/common/insidersBuild/insidersExtensionService.unit.test.ts
Outdated
Show resolved
Hide resolved
src/test/common/insidersBuild/insidersExtensionService.unit.test.ts
Outdated
Show resolved
Hide resolved
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Mostly LGTM. There are a number of things you can do to make this code a bit easier to follow.
@@ -63,4 +69,42 @@ export class InsidersExtensionService implements IExtensionSingleActivationServi | |||
this.disposables.push(this.cmdManager.registerCommand(Commands.SwitchToInsidersDaily, () => this.extensionChannelService.updateChannel('daily'))); | |||
this.disposables.push(this.cmdManager.registerCommand(Commands.SwitchToInsidersWeekly, () => this.extensionChannelService.updateChannel('weekly'))); | |||
} | |||
|
|||
/** |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I see where you're coming from here, but I'm not sure these 3 new methods pull their own weight here. There's just not enough meat to them to pay for the extra cost to readers (e.g. extra boilerplate code, more indirection). Consider folding them back into handleEdgeCases()
and perhaps even folding handleEdgeCases()
into handleChannel()
. Here's one way to do that without having the clutter of the conditions:
public activate() {
this.registerCommandsAndHandlers();
this.handleChannel();
}
private handleChannel() {
const installChannel = this.extensionChannelService.getChannel();
switch (this.decideAction(installChannel)) {
case 'promptToReEnroll':
await this.insidersPrompt.promptToEnrollBackToInsiders();
break;
case 'promptToEnroll':
await this.insidersPrompt.promptToInstallInsiders();
break;
case 'unEnroll':
await this.extensionChannelService.updateChannel('off');
break;
case 'install':
await this.installChannel(installChannel);
break;
}
}
private decideAction(installChannel: ExtensionChannels): string {
if (installChannel === 'off' && !this.extensionChannelService.isChannelUsingDefaultConfiguration) {
return 'promptToReEnroll';
} else if (this.appEnvironment.channel === 'insiders' && !this.insidersPrompt.hasUserBeenNotified.value && this.extensionChannelService.isChannelUsingDefaultConfiguration) {
return 'promptToEnroll';
} else if (installChannel !== 'off' && this.appEnvironment.extensionChannel === 'stable') {
return 'unEnroll';
} else {
return 'install';
}
}
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
To me each action changes based on the current state, I.e. state pattern. Gets rid of reach case statement and the complicated if condition.
E.g. tomorrow if we have another state we still modify both if conditions and the case statement, that's code smell.
Yes it might seem unnecessary, however I feel that code will be easier to follow, and each class does one thing. To me right now the following block alone is complicated, if (installChannel === 'off' && !this.extensionChannelService.isChannelUsingDefaultConfiguration) { return 'promptToReEnroll'; }
, and to me it gets more complicated when you have more of those.
And one way to solve that is if this.shouldPromptToReEnroll
, then we end up with around 4 different methods that basically return a state.
The break down further, we have a state of the class, next simply further using state pattern.
I like that because the state describes the next course of action, that's what we need. We have users who are in a particular state and we need to do something based on users state of extension.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
We could also go with a strategy pattern here, that would still simplify the code and accommodate new methods (instead of the switch statement). However looking at the two, state is there right fit (at least IMHO).
Basically both solve O. In SOLID.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Was referring to @ericsnowcurrently 's review earlier :
So many if conditions in one place leads to harder testability and readability , which was the main reason for doing that. Having documentation for separate cases is also better when you use separate methods, rather than using if statements.
(Not to say I would've to refactor the entire test code as well, does not seem to be worth the effort for me)
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Having documentation for separate cases is also better when you use separate methods, rather than using if statements.
Agreed, we could go another step, self documenting code. Separate classes would make documentation unnecessary 😁
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Revised code is much better, and easier to follow. Would still prefer a state pattern or similar, but the over so objective has been achieved - simplification of code.
I leave further simplification upto you.
Hopefully we won't have further changes based on users current state
of install of extension 😉
For #7473
[ ] Test plan is updated as appropriate[ ]package-lock.json
has been regenerated by runningnpm install
(if dependencies have changed)[ ] The wiki is updated with any design decisions/details.