如何写教程(Tutorials)

注解

教程是完全以学习(Learning)为导向的材料。

教程应当是手把手带领读者通过一系列步骤,从零到一地完成某个小项目的课程(Lessons)。 借助于这个示范项目(Demo),我们可以向新手友好地展示他们能够完成什么样的目标。

具体而言, 用户要学习的是 How, 而不是 What.

  • 在这个过程中,你的身份是一名导师(Tutor),你有义务为学生的所有行为负责。 最终,学生应当能够在你的指示下,通过执行一系列的动作(Actions)达到最终的目标(End)。

  • 需注意的是,“目标” 和 “动作” 将完全由你来设定,这无疑是一项艰巨的工作。

  • 目标必须是有意义的,对于完全零基础的新手来说,也应当是可实现的。

  • 最重要的一点是,在完成教程后,学习者应当能够更好地理解软件本身,以及文档的其它部分。

警告

大多数软件的教程写得很糟糕 —— 甚至完全没有提供教程。 而教程是将学习者转化成用户的关键。 一个糟糕的(或缺失)的教程会阻碍你的项目获得新的用户。

警告

在文档的四种具体分类中,将会花 最多的篇幅 来讲解如何写教程。 这是因为教程的内容是 最容易被初学者误解的,也是最难做好的。 最好的教学方式应当是有老师在场并和学生互动的那种,但这对文档来说不可能。 书面教程充其量只是个远达不到完美的替代品,这也是为什么我们需要投注更多的精力。

教程需要对初学者有帮助,容易遵循,本身有意义且内容极其强大, 并时刻保持最新状态。 你可能会发现编写和维护教程会占用掉和其它三个部分加起来一样多的时间和精力。

以教孩子烹饪为例

假设我们现在需要教会一个小朋友如何烹饪。

作为初次体验,第一次做什么好吃的并不重要。 重点是孩子能够完成它,觉得它很有趣,并获得了信心,想要再来一次。 借助于这些孩子力所能及的事情,我们能够传达有关烹饪的重要知识。 孩子们将了解在厨房里是什么感觉,如何使用餐具,如何处理食物。 基于这些认知,孩子们将能够进行更多不同类型、不同难度的尝试。

使用软件就像烹饪一样,是一门手艺活。 它确实涉及到知识 —— 但它是实践知识,而不是理论知识。

注解

  • 当我们学习一项新手艺或技能时,我们总是从实践中开始学习;

  • 自然地,老师想要教会学生新的知识时,培养兴趣和建立直觉是重中之重。

如何写出好的教程

允许用户边做边学

注解

一开始,我们只能够通过实践来学习任何东西。 —— 这就是我们学会说话和走路的方式。

在你的教程中,允许你的学习者通过实践来学习,而不是仅仅接受纸面上的输入。 主动引导他们不断地思考和输出,但作者在编排内容时请注意:

  • 一切都应该从最简单的地方开始,让学习者体会到一个循序渐进的过程;

  • 最终教程应该在一个合适的目标处停止,并对前面对实践进行适当的总结。

让用户能够开始

警告

在一份教程中,如果你让初学者做的事情不像是有经验人士的做法, 出于教学目的,即使这件事情 “不正确”,但也完全可以接受。 初学者教程和最佳实践手册的性质截然不同。

参见

在 MegEngine 的深度学习零基础教程中,先介绍了使用 funtional 模块搭建模型结构的方式, 这种方式相较于使用 module 来搭建模型的方式十分低效,但对于刚学会 Tensor 概念的初学者来说, 这是最合适的学习路径。如果一开始就将 module 的最佳实践讲给初学者听,可能会让人望而生畏。

教程的重点是让初学者们 开始他的旅程 ,而不是让他们直达最终的目的地。

确保教程有效且可重复

注解

作为导师,你的工作之一是激发初学者的信心:对软件、对教程、对导师,以及对自己的信心。

有很多事情可以促成这一点。比如友好的语气、一致的用语、良好的逻辑和节奏感… 这些都会有帮助。 但最重要的一点是, 你要求初学者做的事情必须有效。

  • 学生需要体会到,按照你的提示去采取行动,能够产生预期的效果;

  • 如果学生的操作产生了错误或者意外的结果,你所提供的教程就是失败品,即使这不是你的错。 当学生在你身边时,你可以采取行动拯救他们;但如果是阅读教程的话,大部分情况下将束手无策。 所以你必须提前防止这种情况发生,考虑到尽可能多的情况。这件事情说起来容易,但做起来很难。

教程必须可靠地可重复。 这也不容易实现:通常人们将基于不同的操作系统、经验水平和工具来使用你的教程。 MegEngine 文档中的教程借助 MegStudio 平台提供一致的云端环境,实现了一定程度的保证。 在其它情况下,我们有必要将足够的背景信息告知初学者,让大家在同一个起跑线。

教程每次都必须适用于所有人, 因此需要定期详细地测试,以确保它们仍然有效。

确保用户立即看到结果

注解

初学者所做的一切都应该是可感知的,无论步骤多么简单,反馈多么细微。

如果你的学生在看到结果之前必须用两页的时间做一些奇怪和难以理解的事情,那太离谱了。 每一个动作的效果都应该尽快显现出来,并且它与动作的联系应该是明显的。

专注具步骤,而非抽象概念

注解

  • 教程的内容必须是具体的,围绕特定的、常见的操作和结果进行设计的。

喜欢一开始就使用抽象描述,尤其是在展示 How 之前定义 What 的教科书一定不适合自学。

抽象可以帮助我们更加有效率的交流,这同时也是赋予计算机程序巨大能量的原因之一。 但所有的学习都是从特殊到一般、从具体到抽象的,困难的是回到初学者视角。 如果在学习者还没掌握更加具体的内容之前就要求他们欣赏你的抽象交流,这样的教程是糟糕的。

提供最低限度的必要解释

警告

不要解释学习者为了完成本教程所不需要知道的任何内容。

这是一个不成熟的教程作者容易犯的老毛病,总是写着写着就开始进行不必要的拓展, 更有甚者会沉浸在一种自我满足的状态中… 控制住你填鸭式表达拓展知识的欲望! 扩展讨论很重要,只是不应该出现在教程中。在教程中,它只能是障碍,或让人分心。 只有最低限度是合适的,不会显得像在卖弄。相反,我们可以主动地链接到文档中其他地方的解释, 并告知学习者如果当前对背后的细节不是很清楚,也不必担心,这不会影响你完成教程。

帮助具有丰富好奇心的学习者保持稳定的节奏,而不是陷入无尽的细节,也是教程作者的责任。

你的教程需要专注于手头的任务。也许你引入的命令有许多其它的选项,或者可能有不同的方式来访问某个 API. 别在意这些,初学者并不需要为了完成教程而了解这些,它们应该出现在进阶指南,或者参考信息中。

教程作者自查清单

在发布你的教程之前,请尝试回答下面的问题:

  • 我很清楚我的教程所面向的对象,并对学习该教程的前置知识要求进行了清晰的说明;

  • 我对完全复现教程所使用的环境信息进行了充分的说明(指导如何配置环境是加分项);

  • 我的教程向读者陈述了接下来他们将尝试进行哪些内容的实践(而不仅仅声明将要学习什么理论);

  • 我的教程能够承诺:如果初学者按照指导进行操作,最终能实现和教程中展示的一致的效果;

  • 我的教程中没有出现对于初学者而言过于抽象的用语,对可能产生疑惑的地方都进行了解释;

  • 我的教程用语是友好的,能够让学生产生源源不断的自信心,很有可能激发进一步学习的意愿;

  • 我的教程中安排的知识点是由易到难的,读者最终一定能完成一个 有意义的 示例项目;

  • 我承诺我的教程是可维护的,即使不再由我负责,其他人也知道如何更新教程中的内容;

  • 我为完成教程的学生提供了进一步的指引,帮助他们知道接下来可以做什么;

  • 通过我的教程,用户将能够更好的理解文档中其他部分的讲解。

一个好的教程是对用户的一份承诺,整个文档依赖教程给用户留下宝贵的第一印象。

“没有教不好的学生,只有不会教的老师。” —— 中国教育家陈鹤琴用于自勉的一句话。

与君共勉。