{"rowid": 226, "title": "Documentation-Driven Design for APIs", "contents": "Documentation is like gift wrapping. It seems like superfluous fluff, but your family tends to be rather disappointed when their presents arrive in supermarket carrier bags, so you have to feign some sort of attempt at making your gift look enticing. Documentation doesn\u2019t have to be all hard work and sellotaping yourself to a table \u2013 you can make it useful and relevant.\n\nDocumentation gets a pretty rough deal. It tends to get left until the end of a project, when some poor developer is assigned the \u2018document project\u2019 ticket and wades through each feature of Whizzy New API 3.0 and needs to recall exactly what each method is meant to do. That\u2019s assuming any time is left for documentation at all. The more common outcome resembles last minute homework scribbled on a post-it note, where just the bare bones of what\u2019s available are put out for your users, and you hope that you\u2019ll spot the inconsistencies and mistakes before they do.\n\nWouldn\u2019t it be nicer for everyone if you could make documentation not only outstanding for your users, but also a valuable tool for your development team \u2013 so much so that you couldn\u2019t imagine writing a line of code before you\u2019d documented it?\n\nDocumentation needs to have three main features:\n\n\n\tIt should have total coverage and document all the features of your project. Private methods should be documented for your developers, and public features need to be available to your users.\n\tIt should be consistent \u2013 a user should know what to expect from your documentation, and terminology should be accurate to your language.\n\tIt should be current \u2013 and that means staying accurate as new versions of your code base are released.\n\n\nBut you can also get these bonuses:\n\n\n\tAct as a suggested specification \u2013 a guide that will aid a developer in making something consistent and usable.\n\tIt can test your API quality.\n\tIt can enhance the communication skills within your development team.\n\n\nSo how do we get our documentation to be rich and full of features, instead of a little worn out like Boxing Day leftovers?\n\nWrite your documentation first\n\nWhen I say first, I mean first. Not after you\u2019ve started writing the code. Not even after you\u2019ve started writing your unit tests. First. You may or may not have been provided with a decent specification, but the first job should be to turn your requirements for a feature into documentation. \n\nIt works best when it takes the form of in-code comments. It works even better when your in-code comments take a standard documentation format that you can later use to generate published documentation for your users. This has the benefit of immediately making your docs as version controlled as your code-base, and it saves having to rewrite, copy or otherwise harass your docs into something legible later on. \n\nAlmost all languages have a self-documentation format these days. My choice of format for JavaScript is JSDocToolkit, and the sort of things I look for are the ability to specify private and public methods, full options object statements (opts as Opts only is a no-no), and the ability to include good examples.\n\nSo, our example for today will be a new festive feature for a JavaScript API. We\u2019ve been asked to specify a sled for Santa to get around the world to give out toys:\n\n\n\tSanta needs to be able to travel around the world in one night to deliver toys to children, and he\u2019ll need some reindeer to pull his sled.\n\n\nAs documentation, it would look like:\n\n/**\n@name Sled\n@extends Vehicle\n@constructor\n@description Create a new sled to send Santa around the world to deliver toys to good kids.\n\t@param {Object} [opts] Options\n\t@param {number} [opts.capacity='50'] Set the capacity of the sled\n\t@param {string} [opts.pilot='santa'] The pilot of the sled.\n@example\n\t// Create a sled and specify some reindeer.\n\tnew Sled().reindeer(['Dasher', 'Dancer', 'Prancer', 'Vixen', 'Comet', 'Cupid']);\n*/\n\nBy breaking it down as documentation, you can, for example, hand this over to another developer without the need to explain the feature in much depth, and they\u2019ll develop something that has to match this piece of documentation. It specifies everything that is important to this feature \u2013 its default values and types, and where it inherits other features from. \n\nWe know that we need to specify some way of setting reindeer to pull the sled and also some toys to give, and so we can quickly specify extra methods for the sled:\n\n/*\n@name vehicle.Sled#reindeer\n@function\n@description Set the reindeer that will pull Santa's sled.\n\t@param {string[]} reindeer A list of the reindeer.\n@example\n\t// specifying some reindeer\n\tSled().reindeer(['Dasher', 'Dancer', 'Rudolph', 'Vixen']);\n*/\n/*\n@name vehicle.Sled#toys\n@function\n@description Add a list of toys and recipients to the Sled.\n\t@param {Object[]} toys A list of toys and who will receive them.\n@example\n\t// Adding toys to the sled\n\tSled().toys([\n\t\t{name:'Brian', toy:'Fire Engine'},\n\t\t{name:'Drew', toy:'Roller-skates'},\n\t\t{name:'Anna', toy:'Play-doh'},\n\t\t...\n\t\t]);\n*/\n\nJob done! You\u2019ve got a specification to share with your team and something useful for your users in the form of full examples, and you didn\u2019t even have to open another text editor.\n\nUse your documentation to share knowledge\n\nDocumentation isn\u2019t just for users. It\u2019s also used by internal developers to explain what they\u2019ve written and how it works. This is especially valuable where the team is large or the code-base sprawling.\n\nSo, returning to our example, the next step would be to share with the rest of the team (or at least a selection of the team if yours is large) what the documentation looks like. This is useful for two main reasons:\n\n\n\tThey can see if they understand what the documentation says the feature will do. It\u2019s best if they haven\u2019t seen the requirement before. If your fellow developers can\u2019t work out what \u2018MagicMethodX\u2019 is going to return from the docs, neither can your users.\n\tThey can check that the feature accomplishes everything that they expect to, and that it\u2019s consistent with the rest of the functionality.\n\n\nOn previous projects, we\u2019ve taken to referring to this stage of the development process as the \u2018bun fight\u2019. It\u2019s a chance for everyone to have an honest say and throw a few pies without actually causing anyone to have to rewrite any code. If you can identify at this stage that a feature is over-complicated, lacking or just plain useless, you\u2019ll all be much happier to throw out a few lines of documentation than you may have been to throw out a partial, or even complete, piece of functionality.\n\nDocumentation has your back\n\nThe final benefit to working in this way is that your documentation not only remains accurate, it\u2019s always as accurate as your latest release. It can\u2019t fall behind. You can increase the likelihood that your docs will remain up to date by unit testing your examples.\n\nReturning to the previous example, we can add a QUnit unit test to the expected output with ease during the build process \u2013 we know exactly how the code will look and, with the @example tag, we can identify easily where to find the bits that need testing. If it\u2019s tested it\u2019ll definitely work as you expect it to when a user copy and pastes it. You\u2019re ensuring quality from idea to implementation.\n\nAs an extra bauble, the best thing about a system like JSDocToolkit is that it\u2019ll take your inline comments and turn them into beautiful sites, as good systems will allow for customised output templates. You\u2019ll be producing full-featured sites for your projects and plugins with almost no extra effort, but all the benefits.", "year": "2010", "author": "Frances Berriman", "author_slug": "francesberriman", "published": "2010-12-11T00:00:00+00:00", "url": "https://24ways.org/2010/documentation-driven-design-for-apis/", "topic": "process"}