This article describes the main tasks and responsibilities involved in writing documentation for Vaadin products.
The documentation for the products is maintained in the product repositories. See the list of product repositories in the Getting Started article.
Documentation of a product or a feature has the following "CCC" basic requirements:
documentation should cover all the features of the product
documentation should be consistent over different products and features. The user should be able trust that the documentation provides the information they need, with consistent vocabulary and style.
documentation should be up-to-date with API and behaviour changes
The development process alternatives are outlined later. The documentation-driven development approach guarantees at least coverage and currentness. Consistence is attained with review.
Documentation is part of your software development process. It’s your task to plan how. The decisions are up to the development teams. You have various options, as discussed next.
When to document?
What does the team write collaboratively?
Own vs other’s
Coder documents his own features and details
Team members document each other’s features
Why to document?
Define the purpose of documentation
Role as specification: an internal communication tool
What documentation should there be?
What kind of structure?
Introduction, basic use, use cases, examples
Where to document?
Docs Site, website, etc.
Repositories, branches, commits
The challenge is described right in the Agile Manifesto:
"Working software over comprehensive documentation."
Hence, agile principles put weight on working software. Does it imply forgetting documentation altogether? No. Documentation is an essential feature of any working software; it doesn’t matter if it works if it can’t be used because of missing documentation.
It’s unclear from the agile principles whether documentation should be considered a separate task after all code development, iteratively after each software iteration, or during coding. How does it imply for the documentation process? There appears to be disagreement about that (Scott W Ambler, Strategies for Agile Software Development).
"Document stable concepts, not speculative concepts, and thereby document as late as possible in the life cycle."
The definition of "life cycle" is somewhat open here. If it means the entire development life cycle, it would break the principle that the software should be shippable at the end of every sprint. It would essentially mean Waterfall creeping into Agile.
Some agree with this (Susan Patch):
Documentation and Coding should proceed in parallel.
How parallel that is, is up to you. It must be parallel within in a sprint. It could be parallel within a commit.
Hence, documentation must exist and be current at the end of each sprint.
It’s part of the Definition of Done.
Documentation is subject to the same iterative development principles as the product. Minimal and extensive documentation have a large gap between.
Consider first the "ultra-Agile" way of documentation, which is similar to Waterfall documentation.
You can have many situations where you write documentation after actual software development:
When following some kind of waterfall model
After impatient prototyping
History catches up
Changes have unexpected side-effects
In the dreaded waterfall model, there are three phases of documentation: requirements, design, and writing user documentation. Developers would write user documentation somewhere at the bottom of the waterfall. At least there would be some requirements design, which are also documentation, and could be used as basis for the user documentation. However, as code is updated right until the release, a huge documentation phase could cause time estimate to fail. If development is pushed tight, it’s easier to give up documentation, which has more loose requirements.
Often, we’re impatient and like to start eating the ham right away, that is, coding. Even though we know that at least some kind of design would be good to write, we often skip that. We start prototyping, trying things out, creating a proof-of-concept. Even a short design phase puts brakes on such technical brainstorming. In such case, try to write the documentation before you present anything to others. Better yet, make the documentation what you present. If you make slides, make the documentation so that you can copy&paste it to or from the slides.
The same problem could arise in iterative development processes if documentation is considered a separate task, even defined as a user story. That situation can be avoided by not doing so.
Sometimes, it isn’t up to us, but history comes to haunt us. You could start working on an existing product or feature with outdated or missing documentation.
Further, an innocent technical implementation change can cause even unexpected changes for a use case. For example, consider changing the loader code for the UI. While it’s merely an implementation detail of the primary use case, opening a UI, it does affect embedding. Such a separate use case might not even have a test case. While such side-effects can sometimes be anticipated, often they go unnoticed. Also, a small urgent change could cause need for a major documentation update, which is easy to push aside.
During the development process, changes in the requirements or design only affect the software, so documentation doesn’t need to be rewritten
Developers can better concentrate on their core task and interest
Development schedules don’t always hold, so if documentation is the final phase before release, it could be truncated or even postponed to meet the deadlines. Hence, the product could be left inadequately or even entirely undocumented.
A writing process is typically as iterative as a software development process. Such iterative revisions successively add details to the content, reorganize it, and improve the completeness and quality of the text. However, when you are writing or revising a text, you become blind to it. When it has just come out of your brain, you are unable to see it as someone else would. For that reason, it’s good to have some time between revisions, so that you can forget what you have written and then reread it like someone else would. The time it takes to forget a text is around two weeks. That long delays fit poorly in the end of development lifecycle.
Documentation needs testing too. While documentation is being reviewed, developers have nothing to do.
Regardless of whether you code or document first, updates to documentation should always be done together with the code commits. The documentation updates should preferably be done in the same commit, but the repository structure or review process may force otherwise. In such case, documentation needs to be committed in a separate documentation commit.
This could cause trouble with our review process, as documentation needs to be reviewed by the Documentation Manager, while code is reviewed by other developers. If a commit needs to be merged quickly, documentation review could delay it too much. We need to get more experience about how this goes.
In iterative development, it may be a burden to always update the documentation along with the code, but we’ll see how that goes.
Write your README first.
First. As in, before you write any code or tests or behaviors or stories or ANYTHING. I know, I know, we’re programmers, dammit, not tech writers. But that’s where you’re wrong. Writing a README is absolutely essential to writing good software. Until you’ve written about your software, you have no idea what you’ll be coding.
a founder and CEO of GitHub
The readme-driven development model promoted by Tom Preston-Werner is a special case of Documentation-Driven Development (DDD).
Documentation is your specification. It describes the basic purpose of the product or feature for solving user’s problems, and how it does that in different use cases.
Write or update documentation
Optional: Write test cases (if you want to go test-driven as well)
Write the code
Write code examples and use them as test cases
This doesn’t imply a reversed waterfall model, but only that you write the documentation for the code you are about to write first. You can make that as iteratively as you want.
You can always start small, writing an overview paragraph or section and an outline. This can come from your very basic project definitions. You can combine the task with writing a ticket for the feature, such as in GitHub or ClickUp, even using the same titles and descriptions. You only need to use descriptive language, what it does, rather than what it should do.
Then, use it as the introductory paragraph in the documentation, and give a basic code example. Once you get a screenshot, add it there. Proceed in the same way for each sub-feature.
When developing a product with a public API, it should always have detailed Javadoc API documentation. The difficulty is in determining the role of the user manual. While it’s fine to have some redundancy, the point-of-views should be rather different.
A user manual describes the product from an abstract top-down viewpoint, including the basic purpose and use, tutorials at different levels of detail, features, tasks, workflows, and properties.
API Documentation gives a more concrete and bottom-up approach. However, for some features, such as where a class is a feature (you can think of a server-side Vaadin component), there isn’t much difference in the viewpoint of the class documentation and its description in the user manual.
Most importantly, a user manual and API documentation are organized differently. A user manual is organized by topics, which can take rather many viewpoints and use cases to using the product, while API documentation is always organized by classes.
For an example, let us consider data binding when documenting a field component. In a user manual you could have:
The Component is an editor field that allows user to edit textual data. The data is bound to the field as its data source, so that when the data changes, the value shown in the field is automatically updated and vice versa, when the user edits the value, it’s written to the data source. In the default unbuffered mode, the user input or modifications are automatically written to the data source, while in the buffered mode, you need to call
commit() explicitly to write them to the data source. The component is by default bound to an internal property data source, but you can use
setPropertyDataSource() to bind it to another source. You can also give the data source in the appropriate constructor.
// Create the component TheComponent component = new Component();
// Have a data source with some initial value ObjectProperty<String> dataSource = new ObjectProperty<String>(String.class); dataSource.setValue("Hello!");
// Bind the component to the data component.setPropertyDataSource(dataSource);
API documentation could have:
Creates a component. An internal default data source is used with initial null value.
Creates a component and binds it to the given property data source.
Binds the field to the given property data source. The field is immediately updated to display the new data. Any previously buffered input is discarded.
Make documentation part of your planning process; how you define specifications and tasks
Plan how to use documentation as an internal communication tool
Assigning tasks also assigns ownership of documentation
If pair-documenting, assign pairs
Documentation for each product lives in the respective product repository at the review server, which is mirrored read-only to GitHub. Pull requests made to GitHub need to be pushed to review for merging.
In the following, we go through some typical branching patterns. We consider how documentation is maintained in them.
In some products, development is done in the master branch, from which a release or maintenance branch is created. Commits to master can be merged to the maintenance branch until it’s released. Later, the changes to the maintenance branch are merged to master.
As documentation is to be done along with code, documentation for new or changed products is to be done to the master branch.
Another common branching pattern is to use feature branches. The documentation is first done in the feature branches along with the actual code in unstable feature branches. The features are merged to the master branch before making a release. Release, stable or unstable, is done from a certain commit, which is tagged.
In this case, the documentation site would point to master. The problem is in keeping the master truly stable. Integrating stable features doesn’t result in a stable master. Pre-releases are done from master, but they aren’t considered as "stable". Getting documentation from tagged releases would prevent documentation fixes.
A branching scheme can combine feature and release branches. New or feature-related documentation is written in feature branches. Ready features are merged to master, which is semi-stable. Release branches are made from the master. Documentation site would always point to a release branch. Corrections are done to release branches, then merged or picked to master.
This approach has issues as well. In some projects, releases include changes such as version numbering that aren’t suitable for merging to master. In such cases, it’s necessary to cherry-pick all changes to be merged.
As the owner of your documentation, you have the responsibility to preview it in a locally running documentation site. You can set it up as described in the README.
Following the documentation-driven process, every commit that changes the behavior or API of the product should include respective changes in the documentation.
Once done with the commit, push it for review as you do with the code, or if working with GitHub, do a pull request.
Add Documentation Manager as reviewer.
Pending documentation review doesn’t prevent merging. In such a case, the review corrections need to be done in a separate commit.