Explain with examples, without writing any

Dr. Gleb Bahmutov PhD
Kensho - Boston / NY / SF

Berlin 2015

Kensho - Boston / NY / SF

35 people, most programmers

"I will write the fastest and most elegant code ever"

- every Kensho engineer

"I will write the most useful and detailed docs ever"

- no one at Kensho

"I will write the most useful and detailed docs ever"

- no programmer

 ever

Popular open source libraries have good documentation by necessity

Internal software has poor 

or non-existent docs

Code documentation

is not a priority for the company's owners

Writing docs is boring for devs

Devs write docs as a chore

Docs add drag

Write 100 documentation examples - earn $0

In this presentation

Convincing the management that good docs matter

Spend less time writing the most useful type of developer docs

Code better Web demos

what is The Most useful part in the  API docs?

the example!

Learning by example

1 example   >=  1 paragraph of text

More examples, please

/**
 * Creates an array with all falsey values removed. 
 * The values `false`, `null`,
 * `0`, `""`, `undefined`, and `NaN` are falsey.
 *
 * @static
 * @memberOf _
 * @category Array
 * @param {Array} array The array to compact.
 * @returns {Array} Returns the new array of filtered values.
 * @example
 *
 * _.compact([0, 1, false, 2, '', 3]);
 * // => [1, 2, 3]
 */
function compact(array) { ... }

Writing more examples is not simple

/**
 * _.compact([0, 1, false, 2, '', 3]);
 * // => [1, 2, 3]
 */
function compact(array) { ... }

No IDE / compiler / language support

Examples get out of sync with code

Manual work!

Really "bad" example - AngularJS $filter 

code + unit tests

/**
    Adds two numbers
    @method add
*/
function add(a, b) { return a + b; }
QUnit.test('adds numbers', function () {
    QUnit.equal(add(2, 3), 5);
});

QUnit test framework

This test is a good example how to use "add"

QUnit.test('adding undefined', function () {
    var undef; 
    QUnit.equal(add(2, undef), '2undefined');
});

This test is a good example how to use "add"

QUnit.test('adds numbers', function () {
    QUnit.equal(add(2, 3), 5);
});
QUnit.test('adding undefined', function () {
    var undef; 
    QUnit.equal(add(2, undef), '2undefined');
});
/**
    Adds two numbers
    @method add
*/
function add(a, b) { return a + b; }
/** @example add */
QUnit.test('adds numbers', function () {
    QUnit.equal(add(2, 3), 5);
});

Documentation

method add(a, b)

Adds two numbers

Example "adds numbers"

QUnit.equal(add(2, 3), 5);

Testing framework specific syntax :(

transform assertions into "human" text

expect(add).to.be.a('function');
QUnit.equal(add(2, 3), 5);
// add is a function
add(2, 3); // 5

Transform using regular expressions or AST

QUnit, gt, jasmine, console.assert, lazy-ass

xplain: API from jsdoc + @example + @sample

xplain -i add.js -i add-spec.js
// creates folder "docs" with HTML API
docs/
    index.html
    styles.css
    utils.js

API doc generated using xplain

4 levels of information

1: description

2: example

3: sample

4: source

bonus: simple API docs static hosting

for public source code - github pages

bonus: simple API docs static hosting

for private source code - kensho/git-pages

Update Markdown

Adds 2 numbers

### adds numbers

    placeholder code
Adds 2 numbers

### adds numbers

    add(2, 3); // 5
xplain -i add.js -i add-spec.js -o README.md

README.md

same name as unit test

simpler web demos

Demos = complicated examples

<!DOCTYPE html>
<html>
<head>
  <title>better demo</title>
  <script src="add.js"></script>
</head>
<body>
  <script>
  console.log(add(2, 3));
  </script>
</body>
</html>

Goal: show `add` in action

Goal: show `add` in action

Need to open console to see the result :(

First, pipe the console to page

<!DOCTYPE html>
<html>
<head>
  <title>better demo</title>
  <script src="add.js"></script>
</head>
<body>
  <script src="https://rawgit.com/bahmutov/ 
    console-log-div/master/console-log-div.js">
  </script>
  <script>
  console.log(add(2, 3));
  </script>
</body>
</html>

Pipe console output

Need to open the page's source to see the code :(

Second, show the source

<!DOCTYPE html>
<html>
<head>
  <title>better demo</title>
  <script src="add.js"></script>
  <style>
    #source {display: block;white-space: pre;
     font-family: monospace;}
    #source:before {content: "add example:";
      font-style: italic;}
    </style>
</head>
<body>
  <script src="https://rawgit.com/bahmutov/ 
    console-log-div/master/console-log-div.js">
  </script>
  <script id="source">
  console.log(add(2, 3));
  </script>

The demo page

bonus: test the demo pages

<!DOCTYPE html>
<html>
<head>
  <title>better demo</title>
  <script src="add.js"></script>
</head>
<body>
  <script src="https://rawgit.com/bahmutov/ 
    console-log-div/master/console-log-div.js">
  </script>
  <script>
  console.log(adds(2, 3));
  </script>
</body>
</html>

The demo page is broken

Test demos

npm install --global clean-console
$ clean-console index.html
checking index.html
phantomjs: opening page index.html
phantomjs: ERROR: ReferenceError: Can't find variable: adds
TRACE:
 -> file:index.html: 17 (in function "global code")
phantomjs process exited with code 1

Use lots of assertions

<script src="https://rawgit.com/bahmutov/
    console-log-div/master/console-log-div.js">
</script>
<script src="https://rawgit.com/bahmutov/
    lazy-ass/master/index.js">
</script>
<script src="https://rawgit.com/kensho/
    check-more-types/master/check-more-types.js">
</script>
<script id="source">
  la(check.fn(add), 'add should be a function', add);
  console.log(add(2, 3));
</script>

Lessons

Write more unit tests

transform the unit tests into documentation

treat web demos as documentation and end to end tests

Explain with examples, without writing any

Berlin 2015