{"_id":"56b536c32d7fc00d0037f496","githubsync":"","project":"56b534f15f1cf00d00cc4759","user":"56b534d0168b5c1700c159a7","version":{"_id":"56b534f25f1cf00d00cc475c","project":"56b534f15f1cf00d00cc4759","__v":4,"createdAt":"2016-02-05T23:49:06.439Z","releaseDate":"2016-02-05T23:49:06.439Z","categories":["56b534f35f1cf00d00cc475d","56b55e5b5f1cf00d00cc477c","56b55e605f1cf00d00cc477d","56b5fac7e205510d001e4cfe"],"is_deprecated":false,"is_hidden":false,"is_beta":false,"is_stable":true,"codename":"","version_clean":"1.0.0","version":"1.0"},"__v":5,"category":{"_id":"56b534f35f1cf00d00cc475d","__v":10,"project":"56b534f15f1cf00d00cc4759","version":"56b534f25f1cf00d00cc475c","pages":["56b534f45f1cf00d00cc475f","56b5368185a6922300d1c538","56b5369a168b5c1700c159a9","56b536b4eed075230097d75e","56b536c32d7fc00d0037f496","56b5370a5997532100bc6c30","56b537147bccae0d00e9a1d0","56b537252d7fc00d0037f498","56b5372e5997532100bc6c32","56b5373d7719bb190014307a"],"sync":{"url":"","isSync":false},"reference":false,"createdAt":"2016-02-05T23:49:07.518Z","from_sync":false,"order":9999,"slug":"documentation","title":"Documentation"},"updates":[],"next":{"pages":[],"description":""},"createdAt":"2016-02-05T23:56:51.360Z","link_external":false,"link_url":"","sync_unique":"","hidden":false,"api":{"results":{"codes":[]},"settings":"","auth":"required","params":[],"url":""},"isReference":false,"order":3,"body":"In the previous section, we took a look at a complex experiment. Here it is again for convenience.\n[block:code]\n{\n  \"codes\": [\n    {\n      \"code\": \"<?php\\n\\n$experiment = (new Scientist\\\\Laboratory)\\n  ->experiment('experiment title')\\n\\t->control($controlCallback)\\n  ->trial('first trial',  $firstTrialCallback)\\n  ->trial('second trial', $secondTrialCallback)\\n  ->trial('third trial',  $thirdTrialCallback)\\n  ->matcher(new Scientist\\\\Matcher\\\\StandardMatcher)\\n  ->chance(50);\\n\\n$value = $experiment->run(3, 'apple', $panda, 42);\",\n      \"language\": \"php\"\n    }\n  ]\n}\n[/block]\nLet's step through this process method by method. That way, we can learn all about the methods that are used to define an experiment. We'll break the method chain apart for convenience.\n[block:api-header]\n{\n  \"type\": \"basic\",\n  \"title\": \"Create Laboratory\"\n}\n[/block]\n\n[block:code]\n{\n  \"codes\": [\n    {\n      \"code\": \"<?php\\n\\n$laboratory = new Scientist\\\\Laboratory;\",\n      \"language\": \"php\"\n    }\n  ]\n}\n[/block]\nAll experiments are created within a Laboratory. You can use the same Laboratory instance to define multiple experiments if you like. Just be sure to start with the `->experiment()` method.\n[block:api-header]\n{\n  \"type\": \"basic\",\n  \"title\": \"Experiment\"\n}\n[/block]\n\n[block:code]\n{\n  \"codes\": [\n    {\n      \"code\": \"<?php\\n\\n$experiment = $laboratory->experiment('experiment title');\",\n      \"language\": \"php\"\n    }\n  ]\n}\n[/block]\nThe `experiment()` method can be used on a Laboratory instance to create a new experiment. Its only parameter is a string, containing the name of the experiment we are about to define. The name serves as a helpful identifier when viewing an experiment results. It's a unique key for our experiment, and shouldn't be used more than once.\n[block:api-header]\n{\n  \"type\": \"basic\",\n  \"title\": \"Control\"\n}\n[/block]\n\n[block:code]\n{\n  \"codes\": [\n    {\n      \"code\": \"<?php\\n\\n$experiment->control(function () { ... });\",\n      \"language\": \"php\"\n    }\n  ]\n}\n[/block]\nThe `control()` method is used to provide our control callable. It's a callback value that contains the original code. The code that we wish to improve upon. The return value from this callable will be the 'control value' for our experiment. Every trial will be compared to it.\n\nCallables can be Closures, or an array representation of a callback. The following is equally acceptable.\n[block:code]\n{\n  \"codes\": [\n    {\n      \"code\": \"<?php\\n\\n$experiment->control([new MyClass, 'someMethod']);\",\n      \"language\": \"php\"\n    }\n  ]\n}\n[/block]\nFor more information about valid callable references, please see the [PHP documentation for `callable`](http://php.net/manual/en/language.types.callable.php).\n[block:api-header]\n{\n  \"type\": \"basic\",\n  \"title\": \"Trial\"\n}\n[/block]\n\n[block:code]\n{\n  \"codes\": [\n    {\n      \"code\": \"<?php\\n\\n$experiment->trial('trial name', function () { ... });\",\n      \"language\": \"php\"\n    }\n  ]\n}\n[/block]\nTrials are our experimental code. We can define as many trials as we like, by continuing to chain the `trial()` method.\n\nThe first parameter to the trial, is a string identifier for the trial, followed by a `callable` containing the trial code.\n\nThe signature of the trial callback **must** be compatible with that of the control. We are improving on the existing functionality, after all. This means that both your `control` and `trial` callbacks must accept the same parameters.\n[block:api-header]\n{\n  \"type\": \"basic\",\n  \"title\": \"Matcher (optional)\"\n}\n[/block]\n\n[block:code]\n{\n  \"codes\": [\n    {\n      \"code\": \"<?php\\n\\n$experiment->matcher(new Scientist\\\\Matcher\\\\StandardMatcher);\",\n      \"language\": \"php\"\n    }\n  ]\n}\n[/block]\nMatchers are used to define the way that a trial must match a control. By default, the experiment will use the `StandardMatcher` which performs a strict `===` comparison on the output of the trial and control callable. The result of the match will be send to all registered journals.\n\nIf the returned value of our control and trials is a little more complex, we can easily define our own matcher class, and provide an instance to the `matcher()` method to allow for more complex evaluation. You'll find more on this technique in the next chapter.\n[block:api-header]\n{\n  \"type\": \"basic\",\n  \"title\": \"Chance (optional)\"\n}\n[/block]\n\n[block:code]\n{\n  \"codes\": [\n    {\n      \"code\": \"<?php\\n\\n$experiment->chance(50);\",\n      \"language\": \"php\"\n    }\n  ]\n}\n[/block]\nThe `chance()` method allows you to specify a % chance of experiment execution. Each time your experiment runs, it will execute the control, and every trial callback. These callbacks, while valuable, might be a little heavy on resources.\n\nIf you're running a busy web application, you may want to use the `chance()` method to execute the experiment only 10% (or any defined value) of the time.\n\nPlease note that the % value is an influenced random chance. There's a small chance you could get two executions, back to back, using a chance of 1%. It's a dice roll.\n[block:api-header]\n{\n  \"type\": \"basic\",\n  \"title\": \"Run\"\n}\n[/block]\n\n[block:code]\n{\n  \"codes\": [\n    {\n      \"code\": \"<?php\\n\\n$value = $experiment->run(3, 'apple', $panda, 42);\",\n      \"language\": \"php\"\n    }\n  ]\n}\n[/block]\nThe `run()` method will execute our experiment. The value returned from `run()` will **always** be the value that is returned from the control callback. Without fail. This means, that the result of trials will never be used in actual application. It's purely there for matching.\n\nYou can optionally supply a number of parameters of any type to the `run()` method. These parameters will be supplied to the callables for both control and trials when the experiment is executed. This saves you having to 'pass them in' manually. Neat, right?!\n[block:api-header]\n{\n  \"type\": \"basic\",\n  \"title\": \"Report\"\n}\n[/block]\n\n[block:code]\n{\n  \"codes\": [\n    {\n      \"code\": \"<?php\\n\\n$report = $experiment->report(3, 'apple', $panda, 42);\",\n      \"language\": \"php\"\n    }\n  ]\n}\n[/block]\nThe `report()` method can optionally be used in place of the `run()` method. Instead of returning the value of the control callable, it will instead return the `Report` instance, containing the results of your experiment. In the [Reports](doc:reports) chapter, you'll find information about how to interrogate a report.\n[block:callout]\n{\n  \"type\": \"info\",\n  \"title\": \"Tip\",\n  \"body\": \"If you've retrieved a report, but still want to use the result of the control callback, then you can retrieve it using `$report->getControl()->getValue();`.\"\n}\n[/block]","excerpt":"","slug":"experiments","type":"basic","title":"Experiments"}
In the previous section, we took a look at a complex experiment. Here it is again for convenience. [block:code] { "codes": [ { "code": "<?php\n\n$experiment = (new Scientist\\Laboratory)\n ->experiment('experiment title')\n\t->control($controlCallback)\n ->trial('first trial', $firstTrialCallback)\n ->trial('second trial', $secondTrialCallback)\n ->trial('third trial', $thirdTrialCallback)\n ->matcher(new Scientist\\Matcher\\StandardMatcher)\n ->chance(50);\n\n$value = $experiment->run(3, 'apple', $panda, 42);", "language": "php" } ] } [/block] Let's step through this process method by method. That way, we can learn all about the methods that are used to define an experiment. We'll break the method chain apart for convenience. [block:api-header] { "type": "basic", "title": "Create Laboratory" } [/block] [block:code] { "codes": [ { "code": "<?php\n\n$laboratory = new Scientist\\Laboratory;", "language": "php" } ] } [/block] All experiments are created within a Laboratory. You can use the same Laboratory instance to define multiple experiments if you like. Just be sure to start with the `->experiment()` method. [block:api-header] { "type": "basic", "title": "Experiment" } [/block] [block:code] { "codes": [ { "code": "<?php\n\n$experiment = $laboratory->experiment('experiment title');", "language": "php" } ] } [/block] The `experiment()` method can be used on a Laboratory instance to create a new experiment. Its only parameter is a string, containing the name of the experiment we are about to define. The name serves as a helpful identifier when viewing an experiment results. It's a unique key for our experiment, and shouldn't be used more than once. [block:api-header] { "type": "basic", "title": "Control" } [/block] [block:code] { "codes": [ { "code": "<?php\n\n$experiment->control(function () { ... });", "language": "php" } ] } [/block] The `control()` method is used to provide our control callable. It's a callback value that contains the original code. The code that we wish to improve upon. The return value from this callable will be the 'control value' for our experiment. Every trial will be compared to it. Callables can be Closures, or an array representation of a callback. The following is equally acceptable. [block:code] { "codes": [ { "code": "<?php\n\n$experiment->control([new MyClass, 'someMethod']);", "language": "php" } ] } [/block] For more information about valid callable references, please see the [PHP documentation for `callable`](http://php.net/manual/en/language.types.callable.php). [block:api-header] { "type": "basic", "title": "Trial" } [/block] [block:code] { "codes": [ { "code": "<?php\n\n$experiment->trial('trial name', function () { ... });", "language": "php" } ] } [/block] Trials are our experimental code. We can define as many trials as we like, by continuing to chain the `trial()` method. The first parameter to the trial, is a string identifier for the trial, followed by a `callable` containing the trial code. The signature of the trial callback **must** be compatible with that of the control. We are improving on the existing functionality, after all. This means that both your `control` and `trial` callbacks must accept the same parameters. [block:api-header] { "type": "basic", "title": "Matcher (optional)" } [/block] [block:code] { "codes": [ { "code": "<?php\n\n$experiment->matcher(new Scientist\\Matcher\\StandardMatcher);", "language": "php" } ] } [/block] Matchers are used to define the way that a trial must match a control. By default, the experiment will use the `StandardMatcher` which performs a strict `===` comparison on the output of the trial and control callable. The result of the match will be send to all registered journals. If the returned value of our control and trials is a little more complex, we can easily define our own matcher class, and provide an instance to the `matcher()` method to allow for more complex evaluation. You'll find more on this technique in the next chapter. [block:api-header] { "type": "basic", "title": "Chance (optional)" } [/block] [block:code] { "codes": [ { "code": "<?php\n\n$experiment->chance(50);", "language": "php" } ] } [/block] The `chance()` method allows you to specify a % chance of experiment execution. Each time your experiment runs, it will execute the control, and every trial callback. These callbacks, while valuable, might be a little heavy on resources. If you're running a busy web application, you may want to use the `chance()` method to execute the experiment only 10% (or any defined value) of the time. Please note that the % value is an influenced random chance. There's a small chance you could get two executions, back to back, using a chance of 1%. It's a dice roll. [block:api-header] { "type": "basic", "title": "Run" } [/block] [block:code] { "codes": [ { "code": "<?php\n\n$value = $experiment->run(3, 'apple', $panda, 42);", "language": "php" } ] } [/block] The `run()` method will execute our experiment. The value returned from `run()` will **always** be the value that is returned from the control callback. Without fail. This means, that the result of trials will never be used in actual application. It's purely there for matching. You can optionally supply a number of parameters of any type to the `run()` method. These parameters will be supplied to the callables for both control and trials when the experiment is executed. This saves you having to 'pass them in' manually. Neat, right?! [block:api-header] { "type": "basic", "title": "Report" } [/block] [block:code] { "codes": [ { "code": "<?php\n\n$report = $experiment->report(3, 'apple', $panda, 42);", "language": "php" } ] } [/block] The `report()` method can optionally be used in place of the `run()` method. Instead of returning the value of the control callable, it will instead return the `Report` instance, containing the results of your experiment. In the [Reports](doc:reports) chapter, you'll find information about how to interrogate a report. [block:callout] { "type": "info", "title": "Tip", "body": "If you've retrieved a report, but still want to use the result of the control callback, then you can retrieve it using `$report->getControl()->getValue();`." } [/block]