Gleb Bahmutov PRO
JavaScript ninja, image processing expert, software quality fanatic
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
Convincing the management that good docs matter
Spend less time writing the most useful type of developer docs
Code better Web demos
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
/**
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
Adds two numbers
Example "adds numbers"
QUnit.equal(add(2, 3), 5);
Testing framework specific syntax :(
expect(add).to.be.a('function');
QUnit.equal(add(2, 3), 5);
// add is a function
add(2, 3); // 5
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
for public source code - github pages
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
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
<!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
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
<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>
Berlin 2015
By Gleb Bahmutov
Humans learn best by example; good technical docs use lots of them. Yet all modern documentation tools (think jsdoc) making writing correct examples and maintaining them a chore. There is no tool support for syntax highlighting, or even guarantee that an example is correct or up to date. On the other hand, solid software projects have lots of well tested, up to date examples. We call them unit tests! In this presentation I will show how to take the unit tests and transform into syntax-agnostic human-friendly examples to be plugged into your docs.
JavaScript ninja, image processing expert, software quality fanatic