Skip to content

Commit 7fb5dee

Browse files
authored
Move opticks readme and create root readme (#89)
* move readme * add monorepo readme * add changeset
1 parent 2cbd454 commit 7fb5dee

7 files changed

Lines changed: 281 additions & 213 deletions

File tree

.changeset/tidy-phones-jam.md

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,5 @@
1+
---
2+
'opticks': patch
3+
---
4+
5+
Add opticks readme

README.md

Lines changed: 40 additions & 213 deletions
Original file line numberDiff line numberDiff line change
@@ -1,236 +1,63 @@
1-
Feature toggles and A/B tests are wonderful, but can easily introduce debt in
2-
your codebase.
1+
# Opticks Monorepo
32

4-
This project allows you to experiment and automatically clean up your JavaScript
5-
experimentation code after the experiment concludes using JSCodeShift codemods.
3+
Welcome to the Opticks monorepo! This repository includes three main packages:
64

7-
The library consists of two related concepts:
5+
- **lib:** (https://www.npmjs.com/package/opticks)
6+
- **cli:** (https://www.npmjs.com/package/opticks-cli)
7+
- **eslint-plugin:** (https://www.npmjs.com/package/eslint-plugin-opticks)
88

9-
- The Toggle library, a simple API for introducing toggles and A/B tests in your
10-
codebase
11-
- Codemods for cleaning up toggle code
9+
Each package has its own directory and corresponding README file with specific instructions and documentation.
1210

13-
# Toggle Library
11+
## Table of Contents
1412

15-
At the heart of our experimentation framework is the `toggle` function.
13+
- [Opticks Monorepo](#opticks-monorepo)
14+
- [Table of Contents](#table-of-contents)
15+
- [Setup](#setup)
16+
- [Building and Testing](#building-and-testing)
17+
- [Publishing Packages](#publishing-packages)
1618

17-
A toggle allows you to switch between multiple experiment variants (a/b/c/...)
18-
and also turn functionality on or off (feature flags)
19+
## Setup
1920

20-
It can be used in a variety of ways:
21+
To get started with the Opticks monorepo, ensure you have the following prerequisites installed:
2122

22-
1. Reading the value of the toggle (boolean, or a/b/c for multi toggles )
23-
1. Execute code or for a variant of a multi toggle
24-
1. Execute code when a boolean toggle is on
23+
- Node.js (version 20.8.0)
24+
- Yarn
2525

26-
We use React at vio.com and some of the code examples use JSX, but the code
27-
and concept is compatible with any front-end framework or architecture.
26+
Clone the repository and install dependencies:
2827

29-
### Opticks vs other experimentation frameworks
30-
31-
The main reason for using the Opticks library is to be able to clean your code
32-
afterwards by providing a predictable experimentation API.
33-
34-
We don't intend to reinvent the wheel and aim to keep it easy to integrate
35-
existing frameworks and services such as Optimizely, LaunchDarkly and
36-
Conductrics behind a simple facade.
37-
38-
## Usage and Integrations
39-
40-
Currently Opticks has two 'integrations' or adapters, a simple one based on a
41-
local key/value store, and one wrapping the Optimizely Full Stack SDK. Once
42-
initialized, using/consuming the toggle decisions is the same.
43-
44-
In the future the integrations will be packaged separately so you can include
45-
the one you need, for now the "simple" is the default and the Optimizely adapter
46-
can be included directly via:
47-
`import Opticks from 'opticks/lib/optimizely'`
48-
49-
## Integrations
50-
51-
### Simple
52-
53-
See the [Simple integration documentation](docs/simple-integration.md).
54-
55-
### Optimizely
56-
57-
See the [Optimizely integration documentation](docs/optimizely-integration.md).
58-
59-
## Toggles
60-
61-
Toggles can be used to implement a/b/c style MVT testing and on/off feature flags as well.
62-
We specify multiple variants of which only one is active at any time.
63-
By convention the variants are named `a` (control), `b`, `c` etc.
64-
65-
### Reading values
66-
67-
While it's recommended to use the strategy described in
68-
[executing code for variants](#executing-code-for-variants), the following shows
69-
how the variant executing and code clean up works under the hood.
70-
71-
The simplest signature is as follows, to read the toggle value directly:
72-
73-
```
74-
toggle(experimentId: string) => { variant: 'a' | 'b' | 'c' | 'd' | ... }
75-
```
76-
77-
For example when the user is assigned to the `b` side:
78-
79-
```
80-
const fooResult = toggle('foo')
81-
if (fooResult === 'b') console.log('b side of the foo experiment')
82-
```
83-
84-
This works fine, but will result in code that will be hard to clean up
85-
automatically. Considering the codemods replace the toggle with the 'winning'
86-
value (`b` in this case):
87-
88-
```
89-
const fooResult = 'b'
90-
if (fooResult === 'b') console.log('b variant of the foo experiment')
91-
```
92-
93-
This would leave your code more messy than necessary. You could skip the
94-
intermediate value but it will still result in awkward leftover code:
95-
96-
```
97-
if (toggle('foo') === 'b') ...
98-
99-
// becomes
100-
if ('b' === 'b') ...
101-
// or
102-
if ('a' === 'b') ...
28+
```bash
29+
git clone https://github.com/viodotcom/opticks.git
30+
cd opticks
31+
yarn install
10332
```
10433

105-
Rather than reading the return value directly, you can map your variant to
106-
arguments to the toggle function, like so:
34+
## Building and Testing
10735

108-
```
109-
// Defines the result if that toggle or experiment wins, either a function that
110-
// will be executed, or any other value
111-
type ToggleResultType = function | any
112-
113-
// do something for a/b/c variant:
114-
toggle(
115-
experimentId,
116-
variantA: ToggleResultType,
117-
variantB: ToggleResultType,
118-
?variantC: ToggleResultType,
119-
...
120-
)
121-
```
36+
To build and test all packages, you can use the following Yarn commands:
12237

123-
The signature might look more complicated, but it allows you to define what the
124-
results for your variants a, b, c etc map to. The first value is the
125-
experimentId, then the values for `a`, `b`, etc.
126-
127-
For instance:
38+
```bash
39+
# Build all packages
40+
yarn workspaces foreach -A run build
12841

42+
# Test all packages
43+
yarn workspaces foreach -A run test
12944
```
130-
// simple boolean switch
131-
const shouldDoSomething = toggle('foo', false, true)
13245

133-
// multiple variants as strings
134-
// 'black' is the default, red and green are variants to experiment with
135-
const buttonColor = toggle('foo', 'black', 'green', 'red')
136-
```
46+
## Publishing Packages
13747

138-
The benefit is that after concluding your experiment, you can integrate the
139-
winning variation's code directly without awkward references to `a` or `b` etc.
48+
To publish a package after making changes, follow these steps:
14049

141-
After you run the codemods to declare `b` the winner, the corresponding raw
142-
value is kept:
50+
1. **Generate a Changeset:**
51+
After making changes to a package, run the following command to generate a changeset:
14352

144-
```
145-
const shouldDoSomething = toggle('foo', false, true)
146-
const buttonColor = toggle('foo', 'black', 'green', 'red')
53+
```bash
54+
npx changeset
55+
```
14756

148-
// becomes:
149-
const shouldDoSomething = true
150-
const buttonColor = 'green'
151-
```
152-
153-
Much better already, but there is more room for improvement, especially if you
154-
want to do things conditionally for a variant.
155-
156-
Consider the following set up:
157-
158-
```
159-
const shouldShowWarning = toggle('shouldShowWarning', false, true)
160-
if (shouldShowWarning) showWarning()
161-
162-
// or directly:
163-
if (toggle('shouldShowWarning', false, true)) showWarning()
164-
```
165-
166-
This would end up with an orphaned conditional after the codemods did their
167-
cleaning:
168-
169-
```
170-
const shouldShowWarning = true
171-
if (shouldShowWarning) showWarning()
172-
173-
// or directly
174-
if (true) showWarning()
175-
```
176-
177-
The next section explains a more useful concept for this type of conditional
178-
branching.
179-
180-
### Executing code for variants
181-
182-
A better approach that allows you to clean the code easier would be to
183-
encapsulate variant logic by executing code from the toggle:
184-
185-
```
186-
const price = 100
187-
const savings = 20
188-
189-
const CTA = toggle(
190-
'CTAWording',
191-
() => `Buy now for just ${price}` // variant a (default)
192-
() => `Buy now for ${price} and save ${savings}`, // variant b
193-
() => `From ${price + savings} to ${price}` // variant c
194-
)
195-
```
196-
197-
Then after running the cleaning codemods when the `b` variant wins:
198-
199-
```
200-
const price = 100
201-
const savings = 20
202-
203-
const CTA = `Buy now for ${price} and save ${savings}`
204-
```
205-
206-
Or for an example of conditionally calling code:
207-
208-
```
209-
alwaysDoSomething()
210-
toggle('shouldShowWarning', null, () => shouldShowWarning())
211-
```
212-
213-
This shows two special concepts of the codemods, passing a `null` and the use of
214-
arrow functions.
215-
Passing `null` allows for full clean up when that branch loses.
216-
For winners, the _body_ of the arrow function is kept as-is.
217-
218-
After running the codemods with the winning `b` variant:
219-
220-
```
221-
alwaysDoSomething()
222-
shouldShowWarning() // no trace this was the result of a winning experiment
223-
```
224-
225-
But if `a` would have won:
226-
227-
```
228-
alwaysDoSomething()
229-
// no trace that something was experimented with but lost
230-
```
57+
Follow the prompts to describe your changes. This will create a changeset file in the `.changeset` directory.
23158

232-
## Removal of dead code
59+
2. **Push Your Changes:**
60+
Push your changes and create a pull request. Once the pull request is merged, a new pull request will be automatically created. This new pull request will remove the changeset file and update the changelog.
23361

234-
Above are just a few examples of how the codemods operate on the code.
235-
For instructions and more recipes, see
236-
[Removal of dead code](docs/dead-code-removal.md).
62+
3. **Merge the Release Pull Request:**
63+
When this automatically created pull request is merged, the relevant package will be published to the npm registry.

0 commit comments

Comments
 (0)