Skip to content

Latest commit

 

History

History
822 lines (517 loc) · 36.3 KB

File metadata and controls

822 lines (517 loc) · 36.3 KB

九、把你的项目记在文档中

文档是开发人员经常忽略的工作,有时也被管理人员忽略。这通常是由于开发周期结束时缺乏时间,以及人们认为自己不擅长写作的事实。其中有些确实很糟糕,但大多数都能够生成良好的文档。

在任何情况下,结果都是由匆忙编写的文档组成的杂乱无章的文档。开发人员最讨厌做这种工作。当现有文档需要更新时,情况会变得更糟。许多项目只是提供了糟糕的、过时的文档,因为经理不知道如何处理这些文档。

但是,在项目开始时设置文档过程,并将文档当作代码模块来处理,这使得文档编制更加容易。当遵循一些规则时,写作甚至可以变得有趣。

本章提供了一些开始记录项目的技巧:

  • 总结最佳实践的七条技术写作规则
  • StructuredText primer,它是大多数 Python 项目中使用的纯文本标记语法
  • 构建良好项目文档的指南

技术写作的七条规则

编写好的文档在很多方面都比编写代码容易。大多数开发人员认为这很难,但是通过遵循一组简单的规则,它变得非常容易。

我们在这里谈论的不是写一本诗集,而是一篇可以用来理解设计、API 或构成代码库的任何内容的综合文本。

每一个开发者都能生产出这样的材料,本节提供了七条规则,适用于所有情况:

  • 分两步写作:专注于想法,然后回顾和塑造你的文本。
  • 针对读者:谁来读?
  • 使用简单的风格:保持笔直和简单。使用好语法。
  • 限制信息范围:一次介绍一个概念。
  • 使用真实的代码示例:“Foos”和“bar”应该避免。
  • 用一种轻而充分的方法:你不是在写一本书!
  • 使用模板:帮助读者养成习惯。

这些规则大多是从 Andreas Rüping 的《敏捷文档:为软件项目生成轻量级文档的模式指南》、Wiley中得到启发和改编的,这本书专注于在软件项目中生成最佳文档。

分两步写

彼得·肘部在牛津大学出版社的*著作《用力量写作:掌握写作过程的技巧》*中解释说,任何人几乎不可能一次写出完美的文本。问题在于,许多开发人员编写文档,并试图直接写出一些完美的文本。他们在这项练习中取得成功的唯一方法是在每两句话后停止写作,把它们读回,并做一些更正。这意味着他们同时关注文本的内容和风格。

这对大脑来说太难了,结果往往不如预期的好。在对文本的含义进行全面思考之前,我们花费了大量的时间和精力来润色文本的风格和形状。

另一种方法是放弃文本的风格和组织,专注于其内容。所有的想法都写在纸上,不管它们是怎么写的。开发人员开始编写一个连续的流,当他或她犯语法错误时,或者对于与内容无关的任何事情,都不会暂停。例如,只要把想法写下来,句子是否勉强可以理解并不重要。他或她只是写下他想对一个粗略的组织说些什么。

通过这样做,开发人员将注意力集中在他或她想说的话上,并且可能会从他或她脑海中获得比他或她最初认为的更多的内容。

自由写作的另一个副作用是,与主题没有直接关系的其他想法很容易进入大脑。一个好的做法是,当它们出现时,把它们写在第二张纸或屏幕上,这样它们就不会丢失,然后回到主要的文字上。

第二步是重读全文并加以润色,以便大家都能理解。润色文本意味着增强其风格,纠正其错误,稍微重新组织它,并删除它所拥有的任何冗余信息。

当专门用于编写文档的时间有限时,一个好的做法是将这段时间分成两半,一部分用于编写内容,另一部分用于清理和组织文本。

关注内容,然后关注风格和清洁度。

以读者为目标

在撰写内容时,作者应该考虑一个简单的问题:谁来阅读?

这并不总是显而易见的,因为技术文本解释了一个软件是如何工作的,并且通常是为每个可能获得和使用代码的人编写的。读者可以是正在寻找问题的适当技术解决方案的研究人员,也可以是需要用它实现功能的开发人员。设计师也可以从架构的角度来阅读它,以了解包是否符合他或她的需求。

好的文档应该遵循一个简单的规则,每个文本应该只有一种阅读器。

这种哲学使写作更容易。作者确切地知道他或她所面对的是什么样的读者。他或她可以提供简明、准确的文档,而不是含糊地针对所有类型的读者。

一个好的做法是提供一个小的介绍性文本,用一句话解释文档的内容,并将读者引导到适当的部分:

Atomisator is a product that fetches RSS feeds and saves them in a database, with a filtering process.

If you are a developer, you might want to look at the API description (api.txt)

If you are a manager, you can read the features list and the FAQ (features.txt)

If you are a designer, you can read the architecture and infrastructure notes (arch.txt)

通过以这种方式指导读者,您可能会生成更好的文档。

在你开始写作之前先了解你的读者群。

使用简单的风格

塞思·戈丁是营销领域最畅销的作家之一。您可能想阅读互联网(上免费提供的释放艾德病毒哈切特书籍http://www.sethgodin.com/ideavirus/downloads/IdeavirusReadandShare.pdf )。

不久前,他在博客上做了一个分析,试图了解他的书为什么卖得这么好。他列出了市场营销领域的所有畅销书,并比较了每一本书中每句话的平均字数。

他意识到他的书每句话的字数最少(十三个字)。赛斯解释说,这个简单的事实证明,读者更喜欢简短的句子,而不是长而时髦的句子。

通过保持句子简短,你的写作将减少提取、处理和理解内容的脑力消耗。编写技术文档旨在为读者提供软件指南。这不是一个虚构的故事,应该更接近你的微波炉注意,而不是最新的斯蒂芬·金小说。

要记住的几个技巧是:

  • 使用简单的句子。它们不应超过两行。
  • 每一段最多由三句或四句话组成,表达一个主要思想。让你的文字呼吸。
  • 不要重复太多。避免新闻风格的想法被反复重复,以确保他们被理解。
  • 不要用几个时态。大多数时候,现在时态已经足够了。
  • 如果你不是一个真正优秀的作家,就不要在课文中开玩笑。在一篇技术性的文章中要搞笑真的很难,很少有作家能掌握它。如果你真的想提炼一些幽默,把它放在代码示例中,你会很好的。

你不是在写小说,所以风格要尽量简单。

限制信息范围

软件中有一个简单的不良文档的迹象,你正在寻找一些你知道存在于某处但你找不到的信息。在花了一段时间阅读目录之后,您开始尝试几个单词组合来 grep 文件,但无法获得您想要的内容。

当作者没有按主题组织文本时,就会发生这种情况。它们可能提供大量的信息,但只是以整体或非逻辑的方式收集。例如,如果读者正在寻找应用程序的总体情况,那么他或她不必阅读底层的 API 文档。

为避免这种影响,段落应集中在给定章节的有意义标题下,全局文档标题应以简短的短语合成内容。

目录可以由所有章节的标题组成。

撰写标题的一个简单实践是问自己:“我要在谷歌上键入什么短语才能找到这个部分?”

使用真实的代码示例

酒吧都是坏公民。当读者试图理解一段代码如何与用法示例一起工作时,有一个不切实际的示例将使其更难理解。

为什么不使用一个真实的例子呢?通常的做法是确保每个代码示例都可以剪切并粘贴到实际程序中。

为了展示一个坏用法的例子,假设我们想展示如何使用parse()函数:

>>> from atomisator.parser import parse
>>> # Let's use it:
>>> stuff = parse('some-feed.xml')
>>> next(stuff)
{'title': 'foo', 'content': 'blabla'}

更好的示例是,当解析器知道如何使用 parse 函数返回提要内容时,该函数作为顶级函数提供:

>>> from atomisator.parser import parse
>>> # Let's use it:
>>> my_feed = parse('http://tarekziade.wordpress.com/feed')
>>> next(my_feed)
{'title': 'eight tips to start with python', 'content': 'The first tip is..., ...'}

这一细微的差别听起来可能有些过分,但实际上它使您的文档更加有用。读者可以将这些行复制到 shell 中,理解 parse 使用 URL 作为参数,并返回包含博客条目的迭代器。

当然,给出一个现实的例子并不总是可能或可行的。这对于非常通用的代码尤其如此。即使是这本书也很少出现名称上下文不重要的模糊foobar字符串。无论如何,你应该一直努力将这种不切实际的例子减少到最少。

代码示例应该可以在实际程序中直接重用。

使用光线充足的方法

在大多数敏捷方法中,文档不是第一公民。与详细的文档相比,制作工作正常的软件是最重要的。因此,正如 Scott Ambler 在其著作敏捷建模:极限编程和统一过程的有效实践**John Wiley&Sons中所解释的,一个好的实践是定义真正的文档需求,而不是创建一组详尽的文档。

例如,让我们看一个简单项目的示例文档——ianitor,它在 GitHub 上的下可用 https://github.com/ClearcodeHQ/ianitor 。它是一个帮助在 Consor service discovery 集群中注册进程的工具,因此它主要针对系统管理员。如果你看一下它的文档,你会发现这只是一个文档(T1 文件)。它只解释了它的工作原理和使用方法。从管理员的角度来看,这就足够了。他们只需要知道如何配置和运行该工具,没有其他人会使用ianitor。本文档通过回答一个问题来限制其范围,“如何在我的服务器上使用ianitor?”

使用模板

维基百科上的每一页都是相似的。一边有一些框用来总结日期或事实。文档开头是一个目录,其中包含指向同一文本中锚的链接。最后总是有一个参考部分。

用户已经习惯了。例如,他们知道可以快速查看目录,如果没有找到他们要查找的信息,他们将直接转到参考部分,查看是否可以找到有关该主题的其他网站。这适用于维基百科上的任何页面。你学习了维基百科方式来提高效率。

因此,使用模板强制使用文档的通用模式,从而使人们能够更高效地使用模板。他们习惯了这种结构,知道如何快速阅读。

为每种文档提供一个模板也为编写者提供了一个快速的开始。

一种重组的文本引物

reStructuredText 也称为 reST(参考http://docutils.sourceforge.net/rst.html )。它是 Python 社区中广泛使用的一种纯文本标记语言,用于记录包。reST 的优点在于文本仍然可读,因为标记语法不会像 LaTeX 那样混淆文本。

以下是此类文件的示例:

=====
Title
=====

Section 1
=========
This *word* has emphasis.

Section 2
=========

Subsection
::::::::::

Text.

reST 以docutils的形式出现,该软件包提供一套脚本,用于将 reST 文件转换为各种格式,例如 HTML、LaTeX、XML,甚至是 S5,Eric Meyer 的幻灯片放映系统(请参阅http://meyerweb.com/eric/tools/s5 )。

作者可以专注于内容,然后根据需要决定如何呈现内容。例如,Python 本身被记录到 reST 中,然后用 HTML 呈现以构建http://docs.python.org 和其他各种格式。

开始编写 reST 时应知道的最低要素是:

  • 截面结构
  • 列表
  • 内联标记
  • 文字块
  • 链接

本节是对语法的快速概述。更多信息,请访问快速参考 http://docutils.sourceforge.net/docs/user/rst/quickref.html ,这是一个开始工作和休息的好地方。

要安装重构文本,请安装docutils

$ pip install docutils

例如,docutils包提供的rst2html脚本将在给定 reST 文件的情况下生成 HTML 输出:

$ more text.txt
Title
=====

content.

$ rst2html.py text.txt
<?xml version="1.0" encoding="utf-8" ?>
...
<html ...>
<head>
...
</head>
<body>
<div class="document" id="title">
<h1 class="title">Title</h1>
<p>content.</p>
</div>
</body>
</html>

剖面结构

文档的标题及其部分使用非字母数字字符加下划线。它们可以在上划线并加下划线,通常的做法是在标题上使用这种双重标记,并在章节中保留一个简单的下划线。

在章节标题下划线最常用的字符按以下优先顺序排列:=, -, _, :, #, +, ^

当一个字符用于一个节时,它与它的级别相关联,并且必须在整个文档中一致地使用它。

考虑下面的代码,例如:

==============
Document title
==============

Introduction to the document content.

Section 1
=========

First document section with two subsections.

Note the ``=`` used as heading underline.

Subsection A
------------

First subsection (A) of Section 1.

Note the ``-`` used as heading underline.

Subsection B
------------
Second subsection (B) of Section 1.

Section 2
=========

Second section of document with one subsection.

Subsection C
------------

Subsection (C) of Section 2.

Section structure

图 1 重新构造转换为 HTML 并在浏览器中呈现的 DText

列表

reST 为具有自动枚举功能的项目符号列表、枚举列表和定义列表提供可读的语法:

Bullet list:

- one
- two
- three

Enumerated list:

1\. one
2\. two
#. auto-enumerated

Definition list:

one
    one is a number.

two
    two is also a number.

Lists

图 2 呈现为 HTML 的不同类型的列表

内联标记

可以使用内联标记设置文本样式:

  • *emphasis*:斜体字
  • **strong emphasis**:黑体字
  • pyinline preformated:内联预格式化文本(通常为单间距,类似于终端)
  • ``a text with a link_:只要文档中提供了超链接,就会替换为超链接(参见链接部分)

文字块

当您需要展示一些代码示例时,可以使用文字块。两个冒号用于标记块,这是一个缩进段落:

This is a code example

::

    >>> 1 + 1
    2

Let's continue our text

不要忘记在::之后和块之后添加一个空行,否则将无法渲染。

请注意,冒号字符可以放在文本行中。在这种情况下,它们将替换为各种呈现格式的单个冒号:

This is a code example::

    >>> 1 + 1
    2

Let's continue our text

如果不想保留单个冒号,可以在前导文本和::之间插入空格。在这种情况下,::将被解释并完全删除。

Literal block

图 3 reST 中呈现为 HTML 的代码示例

链接

只要文档中提供了文本,文本可以通过以两点开头的特殊行更改为外部链接:

Try `Plone CMS`_, it is great ! It is based on Zope_.

.. _`Plone CMS`: http://plone.org
.. _Zope: http://zope.org

通常的做法是在文档末尾对外部链接进行分组。当要链接的文本包含空格时,必须用```py(倒勾)字符包围。

也可以通过在文本中添加标记来使用内部链接:

This is a code example

.. _example:

::

    >>> 1 + 1
    2

Let's continue our text, or maybe go back to
the example_.
```py

部分也是可以使用的目标:

============== Document title

Introduction to the document content.

Section 1

First document section.

Section 2

-> go back to Section 1_

# 建立文档

指导读者和作者的一个更简单的方法是为他们中的每一个人提供帮助和指导正如我们在本章上一节所学到的那样从作者的角度来看这是通过拥有一组可重用的模板以及一个描述如何以及何时在项目中使用它们的指南来实现的它被称为**文档组合**从读者的角度来看能够毫不费力地浏览文档并习惯于高效地查找信息这一点很重要通过构建一个**文档景观**来完成## 建立投资组合

一个软件项目可以拥有多种文档从直接引用代码的低级文档到提供应用程序高级概述的设计文档例如Scott Ambler 在他的书*敏捷建模极限编程和统一过程的有效实践**John Wiley&Sons*中定义了大量文档类型他构建了一个从早期规范到运营文档的投资组合甚至项目管理文档也包含在内因此整个文档需求都是用一组标准化的模板构建的由于完整的投资组合与用于构建软件的方法密切相关因此本章将只关注您可以根据特定需求完成的通用子集建立一个有效的投资组合需要很长时间因为它抓住了你的工作习惯软件项目中的一组常见文档可分为三类*   **设计**包括提供架构信息和底层设计信息的所有文档如类图或数据库图
*   **用法**包括所有关于如何使用软件的文档这可以是烹饪书教程或模块级帮助的形式
*   **操作**提供如何部署升级或操作软件的指南

### 设计

创建此类文档时重要的一点是确保目标读者完全了解并且内容范围有限因此设计文档的通用模板可以为编写者提供一个简单的结构和一些建议这种结构可能包括*   标题
*   著者
*   标签关键字*   说明摘要*   目标谁应该读这个?)
*   内容带图表*   对其他文件的参考

打印时内容最多应为三到四页以确保限制范围如果它变得更大则应将其拆分为多个文档或汇总该模板还提供了作者的姓名和标签列表以管理其演变并简化其分类这将在本章后面介绍reST 中的示例设计文档模板可以如下所示

========================================= Design document title

:Author: Document Author :Tags: document tags separated with spaces

:abstract:

Write here a small abstract about your design document.

.. contents ::

Audience

Explain here who is the target readership.

Content

Write your document here. Do not hesitate to split it in several sections.

References

Put here references, and links to other documents.

### 用法

用法文档描述了如何使用软件的特定部分本文档可以描述低级部分如函数如何工作也可以描述高级部分如用于调用程序的命令行参数这是框架应用程序文档中最重要的部分因为目标读者主要是要重用代码的开发人员三种主要的文件是*   **配方**这是一个简短的文档解释如何做某事这类文档针对一个读者群并侧重于一个特定主题*   **教程**这是一份分步文档解释如何使用软件的一项功能本文档可以参考配方每个实例仅面向一个读者*   **模块助手**这是一个低级文档解释模块包含的内容例如当您通过模块调用`help`内置程序时可以显示此文档#### 配方

配方回答了一个非常具体的问题并提供了解决方案例如ActiveState 在线提供了一个庞大的 Python 配方库开发人员可以在这里描述如何用 Python 做一些事情请参阅[http://code.activestate.com/recipes/langs/python/](http://code.activestate.com/recipes/langs/python/) 。这样一套与单个区域/项目相关的食谱通常被称为*食谱*这些食谱必须简短结构如下*   标题
*   提交人
*   最后更新
*   版本
*   类别
*   描述
*   源代码源代码*   讨论解释代码的文本*   评论来自网络通常情况下它们只有一个屏幕长不涉及太多细节此结构完全符合软件的需要并且可以在通用结构中进行调整其中添加了目标读者并用标签替换类别*   标题短句*   著者
*   标签关键字*   谁应该读这个*   先决条件例如要阅读的其他文档*   问题简短描述*   解决方案主文本一个或两个屏幕*   参考资料指向其他文件的链接日期和版本在这里没有用处因为项目文档应该像项目中的源代码一样进行管理这意味着处理文档的最佳方法是通过版本控制系统进行管理在大多数情况下这与用于项目代码的代码存储库完全相同配方的简单可重用模板如下所示

=========== Recipe name

:Author: Recipe Author :Tags: document tags separated with spaces

:abstract:

Write here a small abstract about your design document.

.. contents ::

Audience

Explain here who is the target readership.

Prerequisites

Write the list of prerequisites for implementing this recipe. This can be additional documents, software, specific libraries, environment settings or just anything that is required beyond the obvious language interpreter.

Problem

Explain the problem that this recipe is trying to solve.

Solution

Give solution to problem explained earlier. This is the core of a recipe.

References

Put here references, and links to other documents.

#### 教程

教程的目的不同于食谱它不是为了解决一个孤立的问题而是描述如何一步一步地使用应用程序的功能这可能比配方更长并且可能涉及应用的许多部分例如Django 在其网站上提供了教程列表*编写第一款 Django 应用程序 1 部分*参考[https://docs.djangoproject.com/en/1.9/intro/tutorial01/](https://docs.djangoproject.com/en/1.9/intro/tutorial01/) 在几个屏幕中解释了如何使用 Django 构建应用程序此类文件的结构应为*   标题短句*   著者
*   标签单词*   说明摘要*   谁应该读这个*   先决条件例如要阅读的其他文档*   教程正文*   参考资料指向其他文件的链接#### 模块助手

可以添加到我们集合中的最后一个模板是模块助手模板模块帮助器引用单个模块并提供其内容的描述以及使用示例一些工具可以通过使用`pydoc`提取文档字符串和计算模块帮助来自动构建此类文档例如如 Epydoc参见[http://epydoc.sourceforge.net](http://epydoc.sourceforge.net) )。因此可以基于 API 自省生成广泛的文档这种文档通常在 Python 框架中提供例如Plone 提供了一个[http://api.plone.org](http://api.plone.org) 服务器用于保存模块帮助程序的最新集合这种方法的主要问题是*   没有对文档真正感兴趣的模块执行智能选择
*   文档可能会混淆代码

此外模块文档提供了一些示例这些示例有时涉及模块的几个部分并且很难在函数和类的 docstring 之间进行划分模块 docstring 可以通过在模块顶部写入文本来实现这一目的但最终会产生一个由文本块而不是代码块组成的混合文件当代码表示的长度小于总长度的 50%这相当令人困惑如果你是作者这是非常好的但是当人们试图阅读代码而不是文档他们将不得不跳过 docstrings 部分另一种方法是在自己的文件中分离文本然后可以通过手动选择来决定哪个 Python 模块将具有其模块帮助文件然后可以将文档从代码库中分离出来并允许它们过自己的生活我们将在下一部分中看到这就是 Python 的文档记录方式许多开发人员不同意文档和代码分离比 docstring 更好这一事实这种方法意味着文档过程完全集成到开发周期中否则它很快就会过时docstrings 方法通过提供代码与其使用示例之间的接近性来解决此问题但不会将其提升到更高的级别可以作为普通文档的一部分使用的文档模块助手的模板非常简单因为在编写内容之前它只包含少量元数据未定义目标因为希望使用模块的是开发人员*   标题模块名称*   著者
*   标签单词*   所容纳之物

### 注

下一章将介绍使用 doctest 和模块助手的测试驱动开发### 操作

操作文档用于描述如何操作软件考虑以下几点*   安装和部署文档
*   行政文件
*   常见问题FAQ文档
*   解释人们如何做出贡献寻求帮助或提供反馈的文档

这些文档非常具体但它们可能使用前面部分中定义的教程模板# 制作自己的投资组合

我们前面讨论的模板只是您可以用来记录软件的基础随着时间的推移您最终将开发自己的模板和文档制作风格但是始终要记住项目文档的轻量级但充分的方法添加的每个文档都应该有一个明确定义的目标读者群并且应该满足实际需要不应该编写没有增加实际价值的文档每个项目都是独特的并且有不同的文档需求例如使用简单的小型终端工具肯定只能使用一个`README`文件作为其文档环境如果目标读者被精确地定义并一致地分组例如系统管理员),那么使用这种最小的单文档方法是完全好的另外不要过于严格地应用提供的模板作为示例提供的一些附加元数据在大型项目或严格形式化的团队中都非常有用例如标记旨在改进大型文档中的文本搜索但在仅由少数文档组成的文档环境中不会提供任何价值此外包括文档作者并不总是一个好主意这种方法在开源项目中尤其值得怀疑在这些项目中您将希望社区也对文档做出贡献在大多数情况下无论是谁作出贡献只要有必要这些文件都会不断更新人们倾向于将文档*作者*也视为文档*所有者*如果每个文档都指定了作者这可能会阻止人们更新文档通常版本控制软件提供的关于真实文档作者的信息比显式提供的元数据注释更清晰更透明真正推荐明确作者的情况是各种设计文档特别是在设计过程严格形式化的项目中最好的例子是包含 Python 语言增强建议的一系列 PEP 文档## 营造景观

上一节中构建的文档组合提供了文档级别的结构但没有提供一种方法来对其进行分组和组织以构建读者将拥有的文档这就是 Andreas Rüping 所称的文档景观指的是读者在浏览文档时使用的心理地图他得出结论组织文档的最佳方法是建立一个逻辑树换句话说组成公文包的不同类型的文档需要在目录树中找到一个位置作者在创建文档时以及读者在寻找文档时必须清楚地看到这个位置浏览文档时的一个很大的帮助是在每一个级别上的索引页它可以驱动作者和读者构建文档环境分两步完成*   为制片人编剧建树
*   在生产者树上为消费者读者构建一棵树

生产者和消费者之间的这种区别很重要因为他们在不同的地方以不同的格式访问文档### 制作人布局图

从制作人的角度来看每个文档的处理与 Python 模块完全相同它应该存储在版本控制系统中并像代码一样工作作家们并不关心他们的散文的最终外观只要有他们只想确保他们正在写一份文件因此这是关于所涉及主题的唯一真相来源存储在文件夹树中的重构文本文件可与软件代码一起在版本控制系统中使用是为生产者构建文档环境的方便解决方案按照惯例`docs`文件夹用作文档树的根目录

$ cd my-project $ find docs docs docs/source docs/source/design docs/source/operations docs/source/usage docs/source/usage/cookbook docs/source/usage/modules docs/source/usage/tutorial

请注意树位于`source`文件夹中因为`docs`文件夹将用作根文件夹以便在下一节中设置专用工具在此基础上可以在每个级别根目录除外添加一个`index.txt`文件解释文件夹包含的文档类型或总结每个子文件夹包含的文档这些索引文件可以定义它们包含的文档列表例如`operations`文件夹可以包含可用的操作文档列表

========== Operations

This section contains operations documents:

− How to install and run the project − How to install and manage a database for the project

重要的是要知道人们往往忘记更新这样的文档列表和目录所以最好让它们自动更新在下一小节中我们将讨论一个工具在许多其他特性中它也可以处理这个用例### 消费者的布局

从消费者的角度来看编制索引文件并以易于阅读且外观良好的格式呈现整个文档非常重要网页是最好的选择并且很容易从重构的文本文件生成**狮身人面像**[http://sphinx.pocoo.org](http://sphinx.pocoo.org) 是一组脚本和`docutils`扩展可用于从文本树生成 HTML 结构例如这个工具用于构建 Python 文档许多项目现在都在使用它来编制文档在其内置功能中它提供了一个非常好的浏览系统以及一个轻量级但足够的客户端 JavaScript 搜索引擎它还使用`pygments`呈现代码示例这会产生非常好的语法亮点Sphinx 可以很容易地配置为与前面部分中定义的文档环境保持一致可与`pip`作为`Sphinx`组件轻松安装开始使用狮身人面像最简单的方法是使用`sphinx-quickstart`脚本此实用程序将与`Makefile`一起生成一个脚本可用于在每次需要时生成 web 文档它将以交互方式询问您一些问题然后引导整个初始文档源代码树和配置文件一旦完成您可以随时轻松调整它假设我们已经引导了整个 Sphinx 环境我们希望看到它的 HTML 表示这可以使用`make html`命令轻松完成

project/docs$ make html sphinx-build -b html -d _build/doctrees . _build/html Running Sphinx v1.3.6 making output directory... loading pickled environment... not yet created building [mo]: targets for 0 po files that are out of date building [html]: targets for 1 source files that are out of date updating environment: 1 added, 0 changed, 0 removed reading sources... [100%] index looking for now-outdated files... none found pickling environment... done checking consistency... done preparing documents... done writing output... [100%] index generating indices... genindex writing additional pages... search copying static files... done copying extra files... done dumping search index in English (code: en) ... done dumping object inventory... done build succeeded. Build finished. The HTML pages are in _build/html.

![Consumer's layout](img/5295_09_04.jpg)

 4 使用 Sphinx 构建文档的示例 HTML 版本–[http://graceful.readthedocs.org/en/latest/](http://graceful.readthedocs.org/en/latest/)

除了文档的 HTML 版本外该工具还构建自动页面如模块列表和索引Sphinx 提供了一些`docutils`扩展来驱动这些功能主要有*   建立目录的指令
*   可用于将文档注册为模块帮助器的标记
*   在索引中添加元素的标记

#### 在索引页上工作

Sphinx 提供了一个`toctree`指令可用于在文档中插入目录并链接到其他文档每一行必须是一个文件及其相对路径从当前文档开始还可以提供 Glob 样式名称来添加多个与表达式匹配的文件例如`cookbook`文件夹中的索引文件我们之前在制作人的环境中定义过可以如下所示

======== Cookbook

Welcome to the Cookbook.

Available recipes:

.. toctree:: :glob: *

使用此语法HTML 页面将显示`cookbook`文件夹中可用的所有重构文本文档的列表此指令可用于所有索引文件以构建可浏览的文档#### 注册模块助手

对于模块助手可以添加一个标记使其自动列出并在模块的索引页面中可用

======= session

.. module:: db.session

The module session...

注意这里的`db`前缀可以用来避免模块冲突Sphinx 将使用它作为模块类别并将该类别中以`db.`开头的所有模块分组#### 添加索引标记

另一个选项可以通过将文档链接到条目来填充索引页

======= session

.. module:: db.session

.. index:: Database Access Session

The module session...

索引页中将添加两个新的条目`Database Access``Session`#### 交叉引用

最后Sphinx 提供了一个内联标记来设置交叉引用例如到模块的链接可以这样做

:mod:db.session


这里,`:mod:`是模块标记的前缀,``db.session``是要链接到的模块的名称(如之前注册的);请记住`:mod:`和前面的元素都是斯芬克斯在 StructuredText 中引入的特定指令。

### 注

斯芬克斯提供了更多的功能,你可以在其网站上发现。例如,*autodoc*功能是一个很好的选择,可以自动提取 doctest 来构建文档。参见[http://sphinx.pocoo.org](http://sphinx.pocoo.org) 。

## 文件构建和持续集成

从消费者的角度来看,Sphinx 确实提高了阅读文档的可读性和体验。如前所述,当它的某些部分与代码紧密耦合时,它特别有用,例如以剂量或模块辅助的形式。虽然这种方法确实更容易确保文档的源版本与文档中的代码相匹配,但并不保证文档读者能够访问最新的编译版本。

如果文档的目标读者对命令行工具不够精通,并且不知道如何将其构建为可浏览和可读的形式,那么仅有最少的源代码表示也是不够的。这就是为什么在提交/推送对代码存储库的任何更改时,自动将文档构建为消费者友好的表单非常重要。

托管使用 Sphinx 构建的文档的最佳方法是生成 HTML 构建,并将其作为静态资源与您选择的 web 服务器一起使用。Sphinx 提供了适当的`Makefile`来使用`make html`命令构建 HTML 文件。由于`make`是一个非常常见的实用程序,因此将此流程与[第 8 章](08.html "Chapter 8. Managing Code")、*管理代码*中讨论的任何连续集成系统进行集成应该非常容易。

如果你正在用 Sphinx 记录一个开源项目,那么通过使用**阅读文档**([可以让你的生活更轻松 https://readthedocs.org/](https://readthedocs.org/) )。这是一项免费服务,用于托管 Sphinx 开源 Python 项目的文档。该配置完全没有任何麻烦,并且非常容易与两种流行的代码托管服务集成:GitHub 和 Bitbucket。在实践中,如果您的帐户已正确连接,并且代码存储库已正确设置,那么只需单击几下即可在读取文档时启用文档托管。

# 总结

本章详细说明了如何:

*   使用一些规则来提高写作效率
*   使用重构文本,蟒蛇的乳胶
*   构建文档组合和环境
*   使用 Sphinx 生成有用的 web 文档

当记录一个项目时,最困难的事情是保持它的准确性和最新性。使文档成为代码存储库的一部分使它变得更容易。从这里开始,每次开发人员更改模块时,他或她也应该更改相应的文档。

在大型项目中,这可能非常困难,在模块的标题中添加相关文档的列表在这种情况下会有所帮助。

确保文档始终准确的补充方法是通过 doctest 将文档与测试结合起来。这将在下一章中介绍,该章介绍测试驱动的开发原则,然后介绍文档驱动的开发。