Skip to content

Generalized client side experiments#7870

Merged
Bjvanminnen merged 5 commits into
stagingfrom
experiments
Apr 14, 2016
Merged

Generalized client side experiments#7870
Bjvanminnen merged 5 commits into
stagingfrom
experiments

Conversation

@Bjvanminnen

Copy link
Copy Markdown
Contributor

Provide a generalized way of experimenting on the client (currently assumes experiments are toggleable).

It's possible I tried to generalize this too early, as it's only needed for one other thing (topInstructions, and soon runModeIndicators). I'm also not too sure I love the design. There's some weirdness in that if we never check to see if any experiments are enabled, we won't parse your query params. Or maybe that's not that weird. I guess we could do the parsing as part of init if we were concerned.

I'm interested in hearing what you think of this.

Comment thread apps/src/experiments.js Outdated
*/
function processQueryParams(queryString) {
Object.keys(experimentList).forEach(function (key) {
var regex = new RegExp(key + '=(true|false)');

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

Though not strictly necessary, it might be nice to make experiment names (and true/false values) case-insensitive. Also to accept 0 or 1 as values.

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

Note: This regex is ambiguous in the case that one queryparam forms the end of another. In the case of your topInstructions experiment, if somebody ever came along and added an Instructions experiment we would also update Instructions every time you tried to set topInstructions via queryparam.

Small and unlikely, but hopefully an easy fix - put a word boundary \b at the beginning of your regex.

@islemaster

Copy link
Copy Markdown
Contributor

Approach seems sound and well-tested. Comments are speculative improvements, but take them or leave them. LGTM.

Comment thread apps/src/experiments.js Outdated
experiments.isEnabled = function (key) {
if (!performedLoad) {
loadFromLocalStorage();
processQueryParams(window.location.search);

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

I'm not sure the one-time load you're doing here gains you anything. In theory, it'd be equally valid to check localstorage and the querystring on demand for each isEnabled check, and it's possible that it's a hair faster as the list of experiments grows to do so - if we have ten experiments and only two are used on a page, you only create/run two RegExp objects against the querystring, instead of ten.

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

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

I think you're right. I don't think we'll ever really need to be in a place where we need to ask the question "What are all the enabled experiments", so tracking them all doesn't have a lot of value. Really, the only part we want is "Is this experiment enabled".

@Bjvanminnen

Copy link
Copy Markdown
Contributor Author

Refactored this significantly. This feels a lot better and simpler

Comment thread apps/src/experiments.js Outdated
*/
experiments.isEnabled = function (key) {
var enabled;
var queryString = this.__TestInterface__.queryString ||

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

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

I don't love this. Can you think of a better way of doing this?

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

At minimum, extracting a getQueryString helper could hide the kludge.

Then, you might be able to have the test monkeypatch over the getQueryString method, so you don't need to expose any special test interface here. I'm not sure if that's 'cleaner' than what you already have though.

It's too bad you can't just overwrite window.location.search since you already have to run this test in a browser context. You could always set up this method so that you have to inject window into it, but that's a step away from the simplicity of your interface.

@Bjvanminnen Bjvanminnen merged commit cb1c360 into staging Apr 14, 2016
@Bjvanminnen Bjvanminnen deleted the experiments branch April 14, 2016 19:25
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