每个工程师都应该是作家 (ZH)
2022年11月30日 08:00
/*@jsxRuntime automatic @jsxImportSource react*/
const {Fragment: _Fragment, jsx: _jsx, jsxs: _jsxs} = arguments[0];
const {useMDXComponents: _provideComponents} = arguments[0];
function _createMdxContent(props) {
const _components = Object.assign({
h2: "h2",
p: "p",
a: "a",
h3: "h3",
ul: "ul",
li: "li",
code: "code",
pre: "pre",
strong: "strong",
em: "em",
table: "table",
thead: "thead",
tr: "tr",
th: "th",
tbody: "tbody",
td: "td"
}, _provideComponents(), props.components);
return _jsxs(_Fragment, {
children: [_jsx(_components.h2, {
id: "前言",
children: "前言"
}), "\n", _jsxs(_components.p, {
children: ["google 在 ", _jsx(_components.a, {
href: "http://developers.google.com/",
children: "developers.google.com"
}), " 上提供了一份", _jsx(_components.a, {
href: "https://developers.google.com/tech-writing",
children: "技术写作课程"
}), ",本文记录了笔者阅读这份技术写作课程时的一些笔记与个人理解"]
}), "\n", _jsx(_components.h2, {
id: "词汇的使用words",
children: "词汇的使用(Words)"
}), "\n", _jsx(_components.h3, {
id: "术语的定义",
children: "术语的定义"
}), "\n", _jsx(_components.p, {
children: "当使用一个术语时,文章的受众可能对这个术语并不熟悉,我们对这样的一个术语的处理可以分为以下两种情况:"
}), "\n", _jsxs(_components.ul, {
children: ["\n", _jsx(_components.li, {
children: "文章不准备花大量时间在这个术语上,且这个术语在业内已经有过很明确的定义。那我们在文章中第一次使用这个术语时,直接链接到已有的解释就可以了,不需要自己解释一遍(重复造轮子)"
}), "\n", _jsx(_components.li, {
children: "文章有章节或段落专门解释此术语,那么这时,对于此术语,在文中就需要给一个明确的定义。如果文章介绍了很多这样的术语,那我们最好将这样的一些术语集合起来,放到专门的术语表中"
}), "\n"]
}), "\n", _jsx(_components.h3, {
id: "保持术语的一致性",
children: "保持术语的一致性"
}), "\n", _jsx(_components.p, {
children: "原文的这句话很有意思:"
}), "\n", _jsxs(_components.ul, {
children: ["\n", _jsx(_components.li, {
children: "If you change the name of a variable midway through a method, your code won't compile. Similarly, if you rename a term in the middle of a document, your ideas won't compile (in your users' heads)."
}), "\n"]
}), "\n", _jsx(_components.p, {
children: "如果在一个方法中改变了一个变量的名称,那我们的代码是不会通过编译的,同样的,如果我们在文章中突然改变了一个术语的命名,那读者理解我们文章内容就会变得更困难"
}), "\n", _jsx(_components.p, {
children: "原文给出了一个例子:"
}), "\n", _jsxs(_components.ul, {
children: ["\n", _jsx(_components.li, {
children: "Protocol Buffers provide their own definition language. Blah, blah, blah. And that's why protobufs have won so many county fairs."
}), "\n"]
}), "\n", _jsxs(_components.p, {
children: ["在这个例子中, ", _jsx(_components.code, {
children: "Protocol Buffers"
}), " 这个术语在最后一句变成了 ", _jsx(_components.code, {
children: "protobufs"
}), " ,这样就会让读者感到费解"]
}), "\n", _jsx(_components.p, {
children: "关于为什么需要保持术语的一致性,除了减少读者的理解成本,原文中还有一段非常出色的解释:"
}), "\n", _jsxs(_components.ul, {
children: ["\n", _jsx(_components.li, {
children: "When I encounter two words that seem to be synonyms, I wonder if the author is trying to signal a subtle distinction that I need to track down and understand."
}), "\n", _jsx(_components.li, {
children: "当我发现两个词语好像是近义词时,我会思考作者是不是在暗示我需要追踪和理解他们之间的微妙差别"
}), "\n"]
}), "\n", _jsx(_components.p, {
children: "如果一个术语太长了,你可能觉得在文章中从头到尾都保持一致会很累,那你可以采取这样的方法:"
}), "\n", _jsx(_components.pre, {
children: _jsx(_components.code, {
className: "language-markdown",
children: "**Protocol Buffers** (or **protobufs** for short) provide their own definition language. Blah, blah, blah. And that's why protobufs have won so many county fairs.\n"
})
}), "\n", _jsx(_components.p, {
children: "即在第一次引入这个术语时就重命名一下"
}), "\n", _jsx(_components.h3, {
id: "正确的使用缩略语",
children: "正确的使用缩略语"
}), "\n", _jsx(_components.p, {
children: "在开始引入文章受众并不熟悉的缩略语时,应该先将全称拼写出来,将缩略语放入括号中,并加粗全称以及缩略语。例子:"
}), "\n", _jsx(_components.pre, {
children: _jsx(_components.code, {
className: "language-markdown",
children: "This document is for engineers who are new to the **Telekinetic Tactile Network (TTN)** or need to understand how to order TTN replacement parts through finger motions.\n"
})
}), "\n", _jsxs(_components.p, {
children: ["然后在下文中再使用 ", _jsx(_components.code, {
children: "TNN"
}), " 这个缩略语"]
}), "\n", _jsx(_components.p, {
children: "正确的使用缩略语很简单,但是我们是否真的需要使用缩略语?"
}), "\n", _jsxs(_components.p, {
children: ["固然,缩略语可以减少句子的长度,如 ", _jsx(_components.code, {
children: "TNN"
}), " 与 ", _jsx(_components.code, {
children: "Telekinetic Tactile Network"
}), " 相比就少了两个词汇,但是在读者的脑子中从 ", _jsx(_components.code, {
children: "Telekinetic Tactile Network"
}), " 到 ", _jsx(_components.code, {
children: "TNN"
}), " 是需要时间转换的。如果缩略语的使用频率并不高是没有必要引入的。当然,某些约定俗成的缩略语除外,例如 ", _jsx(_components.code, {
children: "HTML"
}), " ,你可能根本想不起来原拼是啥了"]
}), "\n", _jsx(_components.p, {
children: "总结缩略词使用的要点:"
}), "\n", _jsxs(_components.ul, {
children: ["\n", _jsx(_components.li, {
children: "不需要定义出现频率很低的缩略语"
}), "\n", _jsxs(_components.li, {
children: ["定义缩略语时遵守以下两条原则:", "\n", _jsxs(_components.ul, {
children: ["\n", _jsx(_components.li, {
children: "缩略语明显要短于全称"
}), "\n", _jsx(_components.li, {
children: "缩略语在文中出现了很多次"
}), "\n"]
}), "\n"]
}), "\n"]
}), "\n", _jsx(_components.h3, {
id: "正视模棱两可的代词",
children: "正视模棱两可的代词"
}), "\n", _jsx(_components.p, {
children: "在这一节中,原文行云流水,用编程中的指针来比喻代词,非常恰当的形容了代词, 大意:多数代词指向之前使用的名词,代词就像编程中的指针一样,容易引发错误。不恰当地使用代词会在读者的头脑中造成等同于空指针错误的认知错误。很多时候都应该避免使用代词,而直接使用代词指向的名词"
}), "\n", _jsx(_components.p, {
children: "代词使用要点:"
}), "\n", _jsxs(_components.ul, {
children: ["\n", _jsxs(_components.li, {
children: ["只在介绍了一个名词后再使用指向该名词的代词;", _jsx(_components.strong, {
children: "永远不要"
}), "在此名词介绍前使用代词"]
}), "\n", _jsx(_components.li, {
children: "尽可能的缩短名词和指向此名词的代词的距离。如果名词和代词在一段话中相隔 5 个单词以上,都要考虑是否直接使用名词"
}), "\n", _jsx(_components.li, {
children: "如果介绍了名词 A, 紧接着又介绍了名词 B, 那之后再使用 A 时,切勿使用代词来指向 A, 不然读者一定特别容易混淆 A 与 B"
}), "\n"]
}), "\n", _jsx(_components.h2, {
id: "主动语态",
children: "主动语态"
}), "\n", _jsx(_components.p, {
children: "在主动语态这一节中,原文花了大量的篇幅讲解主动语态与被动语态的区别,识别主动语态与被动语态的方法。而对于写作有指导意义的是原文强调,在技术写作中应该尽量多的使用主动语态,主要有以下优势:"
}), "\n", _jsxs(_components.ul, {
children: ["\n", _jsx(_components.li, {
children: "读者在阅读一个被动语态的句子时,往往会在脑中转换成主动语态来理解。使用主动语态有助于减少读者理解成本。"
}), "\n", _jsx(_components.li, {
children: "被动语态相较于主动语态而言,往往会颠倒句子顺序。"
}), "\n", _jsx(_components.li, {
children: "主动语态往往更短。"
}), "\n"]
}), "\n", _jsx(_components.h2, {
id: "明确的句式",
children: "明确的句式"
}), "\n", _jsxs(_components.ul, {
children: ["\n", _jsx(_components.li, {
children: "Comedy writers seek the funniest results, horror writers strive for the scariest, and technical writers aim for the clearest."
}), "\n"]
}), "\n", _jsx(_components.p, {
children: "在技术写作中,文章表述清晰,通俗易懂应该是我们的最高追求目标。这一节介绍了一些方法,可以让我们的句子更清晰,优美。"
}), "\n", _jsx(_components.h3, {
id: "选择有力的动词strong-verb",
children: "选择有力的动词(strong verb)"
}), "\n", _jsx(_components.p, {
children: "什么是有力的动词?原文对有力的动词是这样形容的:precise, strong, specific。相对有力的动词,原文这样形容无力的动词(week verb): imprecise, weak, or generic。"
}), "\n", _jsx(_components.p, {
children: "无力的动词如下:"
}), "\n", _jsxs(_components.ul, {
children: ["\n", _jsxs(_components.li, {
children: [_jsx(_components.em, {
children: "be"
}), " 的变体:is, are, am, was, were, etc."]
}), "\n", _jsx(_components.li, {
children: "occur"
}), "\n", _jsx(_components.li, {
children: "happen"
}), "\n"]
}), "\n", _jsx(_components.p, {
children: "可在以下表格中对比使用了无力的动词与使用了有力的动词的句子:"
}), "\n", _jsxs(_components.table, {
children: [_jsx(_components.thead, {
children: _jsxs(_components.tr, {
children: [_jsx(_components.th, {
children: "week Verb"
}), _jsx(_components.th, {
children: "Strong Verb"
})]
})
}), _jsxs(_components.tbody, {
children: [_jsxs(_components.tr, {
children: [_jsx(_components.td, {
children: "The exception occurs when dividing by zero."
}), _jsx(_components.td, {
children: "Dividing by zero raises the exception."
})]
}), _jsxs(_components.tr, {
children: [_jsx(_components.td, {
children: "This error message happens when..."
}), _jsx(_components.td, {
children: "The system generates this error message when..."
})]
}), _jsxs(_components.tr, {
children: [_jsx(_components.td, {
children: "We are very careful to ensure..."
}), _jsx(_components.td, {
children: "We carefully ensure..."
})]
})]
})]
}), "\n", _jsx(_components.p, {
children: "总而言之,无力的动词在文章中往往引入如下缺陷:"
}), "\n", _jsxs(_components.ul, {
children: ["\n", _jsx(_components.li, {
children: "动词的不精确或缺失"
}), "\n", _jsx(_components.li, {
children: "被动语态"
}), "\n"]
}), "\n", _jsx(_components.h3, {
id: "减少-there-are--there-is",
children: "减少 There are / There is"
}), "\n", _jsx(_components.p, {
children: "There are / There is 的句型往往伴随泛用的名词/动词,如上文所述,泛用的名词/动词往往是无力的。一般来讲,There are / There is 开头的句子可以转换成更明确的句子:"
}), "\n", _jsx(_components.pre, {
children: _jsx(_components.code, {
className: "language-markdown",
children: "There is a low-level, TensorFlow, Python interface to load a saved model.\n"
})
}), "\n", _jsx(_components.pre, {
children: _jsx(_components.code, {
className: "language-markdown",
children: "TensorFlow provides a low-level Python interface to load a saved model.\n"
})
}), "\n", _jsx(_components.h3, {
id: "减少形容词和副词的使用",
children: "减少形容词和副词的使用"
}), "\n", _jsx(_components.p, {
children: "形容词与副词的恰当使用可以提升诗歌与散文的质量,但是在技术写作中往往会分散读者的注意力,可以对比一下两个句子来感受:"
}), "\n", _jsx(_components.pre, {
children: _jsx(_components.code, {
className: "language-markdown",
children: "Setting this flag makes the application run screamingly fast.\n"
})
}), "\n", _jsx(_components.pre, {
children: _jsx(_components.code, {
className: "language-markdown",
children: "Setting this flag makes the application run 225-250% faster.\n"
})
}), "\n", _jsxs(_components.p, {
children: ["与其使用 ", _jsx(_components.code, {
children: "screamingly"
}), " 这样的副词,", _jsx(_components.code, {
children: "225-250%"
}), " 这样的数据往往更加直观。"]
}), "\n", _jsx(_components.h2, {
id: "减少句子的长度",
children: "减少句子的长度"
}), "\n", _jsx(_components.p, {
children: "为什么需要减少句子的长度?我们可以对比编程,往往大家会追求写出更简短的代码,通常有以下理由:"
}), "\n", _jsxs(_components.ul, {
children: ["\n", _jsx(_components.li, {
children: "可读性"
}), "\n", _jsx(_components.li, {
children: "维护性"
}), "\n", _jsx(_components.li, {
children: "长段代码相较于短一点的代码,容易引人额外的 bug 状况"
}), "\n"]
}), "\n", _jsx(_components.p, {
children: "减少句子长度的理由是一样的。相较于长句,短句更加简洁有力,易于阅读。"
}), "\n", _jsx(_components.h3, {
id: "一句话一个想法",
children: "一句话一个想法"
}), "\n", _jsx(_components.p, {
children: "尝试在一句话中表达多个想法会增加阅读理解难度。对比如下两段话:"
}), "\n", _jsx(_components.p, {
children: "The late 1950s was a key era for programming languages because IBM introduced Fortran in 1957 and John McCarthy introduced Lisp the following year, which gave programmers both an iterative way of solving problems and a recursive way."
}), "\n", _jsx(_components.p, {
children: "The late 1950s was a key era for programming languages. IBM introduced Fortran in 1957. John McCarthy invented Lisp the following year. Consequently, by the late 1950s, programmers could solve problems iteratively or recursively."
}), "\n", _jsx(_components.p, {
children: "很明显,将一段又臭又长的句子拆分成几个短句更容易阅读。对比编程, 类似于 single responsibility principle。"
}), "\n", _jsx(_components.h3, {
id: "将长句拆分成列表",
children: "将长句拆分成列表"
}), "\n", _jsxs(_components.p, {
children: ["很多长句往往可以拆分成短句列表,如含有 ", _jsx(_components.code, {
children: "or"
}), " 的长句:"]
}), "\n", _jsxs(_components.p, {
children: ["To alter the usual flow of a loop, you may use either a ", _jsx(_components.strong, {
children: "break"
}), "\nstatement (which hops you out of the current loop) or a ", _jsx(_components.strong, {
children: "continue"
}), "\nstatement (which skips past the remainder of the current iteration of the current loop)."]
}), "\n", _jsx(_components.p, {
children: "拆分成列表:"
}), "\n", _jsxs(_components.ul, {
children: ["\n", _jsxs(_components.li, {
children: [_jsx(_components.code, {
children: "break"
}), ", which hops you out of the current loop."]
}), "\n", _jsxs(_components.li, {
children: [_jsx(_components.code, {
children: "continue"
}), ", which skips past the remainder of the current iteration of the current loop."]
}), "\n"]
}), "\n", _jsx(_components.h3, {
id: "省略无关的词语",
children: "省略无关的词语"
}), "\n", _jsx(_components.p, {
children: "原文中有一个表格可以感受此点:"
}), "\n", _jsxs(_components.table, {
children: [_jsx(_components.thead, {
children: _jsxs(_components.tr, {
children: [_jsx(_components.th, {
children: "Wordy"
}), _jsx(_components.th, {
children: "Concise"
})]
})
}), _jsxs(_components.tbody, {
children: [_jsxs(_components.tr, {
children: [_jsx(_components.td, {
children: "at this point in time"
}), _jsx(_components.td, {
children: "now"
})]
}), _jsxs(_components.tr, {
children: [_jsx(_components.td, {
children: "determine the location of"
}), _jsx(_components.td, {
children: "find"
})]
}), _jsxs(_components.tr, {
children: [_jsx(_components.td, {
children: "is able to"
}), _jsx(_components.td, {
children: "can"
})]
})]
})]
}), "\n", _jsx(_components.p, {
children: "适当的替换句子中的短语可以让文章显得不那么啰里八嗦"
})]
});
}
function MDXContent(props = {}) {
const {wrapper: MDXLayout} = Object.assign({}, _provideComponents(), props.components);
return MDXLayout ? _jsx(MDXLayout, Object.assign({}, props, {
children: _jsx(_createMdxContent, props)
})) : _createMdxContent(props);
}
return {
default: MDXContent
};