mirror of
https://github.com/oldratlee/translations.git
synced 2026-02-02 17:59:34 +08:00
format cleanup
This commit is contained in:
@@ -4,7 +4,7 @@
|
||||
|
||||
# `API`设计原则 - `Qt`官网的设计实践总结
|
||||
|
||||
## 🍎 译序
|
||||
## 🍎 译序
|
||||
|
||||
`Qt`的设计水准在业界很有口碑,一致、易于掌握和强大的`API`是`Qt`最著名的优点之一。此文既是`Qt`官网上的`API`设计指导准则,也是`Qt`在`API`设计上的实践总结。虽然`Qt`用的是`C++`,但其中设计原则和思考是具有普适性的(如果你对`C++`还不精通,可以忽略与`C++`强相关或是过于细节的部分,仍然可以学习或梳理关于`API`设计最有价值的内容)。整个篇幅中有很多示例,是关于`API`设计一篇难得的好文章。
|
||||
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
原文链接:[A generic input/output API in Java](https://dzone.com/articles/generic-inputoutput-api-java) - _Rickard Öberg_ (PS:[文章原始链路](http://www.jroller.com/rickard/entry/a_generic_input_output_api)已失效)
|
||||
译文发在:[【译】Java的通用I/O API](http://oldratlee.com/474/tech/java/generic-io-api-in-java-and-api-design.html),2012-05-11
|
||||
|
||||
## 🍎 译序
|
||||
## 🍎 译序
|
||||
|
||||
本文给出了一个通用`Java` `IO` `API`设计,并且有`API`的`Demo`代码。
|
||||
|
||||
@@ -10,27 +10,28 @@
|
||||
|
||||
设计偏向是艺术,一个赏心悦目的设计,尤其是`API`设计,旁人看来多是妙手偶得的感觉,如果能有些章可循真是一件美事。
|
||||
|
||||
给出 _**减少艺术的艺术工作量**_ 的方法的人是 **大师**。
|
||||
给出 _**减少艺术的艺术工作量**_ 的方法的人是 **大师**。 ❤️
|
||||
|
||||
### 目录
|
||||
# `Java`的通用`I/O` `API`设计
|
||||
|
||||
-------------------------------------------------------------------------------
|
||||
|
||||
<img src="input-output.jpg" align="right" />
|
||||
|
||||
<!-- START doctoc generated TOC please keep comment here to allow auto update -->
|
||||
<!-- DON'T EDIT THIS SECTION, INSTEAD RE-RUN doctoc TO UPDATE -->
|
||||
|
||||
|
||||
- [`Java`的通用`I/O` `API`设计](#java%E7%9A%84%E9%80%9A%E7%94%A8io-api%E8%AE%BE%E8%AE%A1)
|
||||
- [API](#api)
|
||||
- [标准化`I/O`](#%E6%A0%87%E5%87%86%E5%8C%96io)
|
||||
- [拦截传输过程](#%E6%8B%A6%E6%88%AA%E4%BC%A0%E8%BE%93%E8%BF%87%E7%A8%8B)
|
||||
- [Usage in the `Qi4j` `SPI`](#usage-in-the-qi4j-spi)
|
||||
- [结论](#%E7%BB%93%E8%AE%BA)
|
||||
- [API](#api)
|
||||
- [标准化`I/O`](#%E6%A0%87%E5%87%86%E5%8C%96io)
|
||||
- [拦截传输过程](#%E6%8B%A6%E6%88%AA%E4%BC%A0%E8%BE%93%E8%BF%87%E7%A8%8B)
|
||||
- [Usage in the `Qi4j` `SPI`](#usage-in-the-qi4j-spi)
|
||||
- [结论](#%E7%BB%93%E8%AE%BA)
|
||||
- [译跋](#%E8%AF%91%E8%B7%8B)
|
||||
|
||||
<!-- END doctoc generated TOC please keep comment here to allow auto update -->
|
||||
|
||||
`Java`的通用`I/O` `API`设计
|
||||
=========================
|
||||
|
||||

|
||||
-------------------------------------------------------------------------------
|
||||
|
||||
上周处理了很多数据搬移,有原始`byte`形式的,也有`String`形式的,还有`SPI`和领域级对象形式。这些活让我觉得,以可伸缩、高性能、正确处理错误的方式把数据从一处搬到另一处,是非常有难度。我要一遍又一遍做一些事,比如从文件中读出`String`。
|
||||
|
||||
@@ -69,12 +70,11 @@
|
||||
行左边的数字是我标识的4个部分。
|
||||
|
||||
1. 客户代码,初始化了传输,要知道输入和输出的源。
|
||||
1. 从输入中读的代码。
|
||||
1. 辅助代码,用于跟踪整个过程。这些代码我希望能够重用,而不管是何种传输的类型。
|
||||
1. 最后这个部分是接收数据,写数据。这个代码,我要批量读写,可以在第2第4部分修改,改成一次处理多行。
|
||||
1. 从输入中读的代码。
|
||||
1. 辅助代码,用于跟踪整个过程。这些代码我希望能够重用,而不管是何种传输的类型。
|
||||
1. 最后这个部分是接收数据,写数据。这个代码,我要批量读写,可以在第2第4部分修改,改成一次处理多行。
|
||||
|
||||
API
|
||||
---------------------------------------
|
||||
## API
|
||||
|
||||
一旦明确上面划分的内容,剩下就只是为每个部分整理成一个接口,并保证在各种场景能方便使用。结果如下。 首先要有输入,即`Input`接口:
|
||||
|
||||
@@ -110,7 +110,7 @@ public interface Sender<T, SenderThrowableType extends Throwable>
|
||||
}
|
||||
```
|
||||
|
||||
`Output`调用`sendTo`方法,传入一个`Receiver`,`Sender`使用这个`Receiver`来发送一个一个的数据。`Sender`在这个时候发起传输,把类型数据`T`传输到`Receiver`,一次一个。`Receiver`接口如下:
|
||||
`Output`调用`sendTo`方法,传入一个`Receiver`,`Sender`使用这个`Receiver`来发送一个一个的数据。`Sender`在这个时候发起传输,把类型数据`T`传输到`Receiver`,一次一个。`Receiver`接口如下:
|
||||
|
||||
```java
|
||||
public interface Receiver<T, ReceiverThrowableType extends Throwable>
|
||||
@@ -124,8 +124,7 @@ public interface Receiver<T, ReceiverThrowableType extends Throwable>
|
||||
|
||||
这个简单的模式在发送方和接收方各有2个接口,并保持了以可伸缩、高性能和容错的方式传输数据的潜能。
|
||||
|
||||
标准化`I/O`
|
||||
---------------------------------------
|
||||
## 标准化`I/O`
|
||||
|
||||
上文的`API`定义了数据发送和接收的契约,然后可以制定几个输入输出的标准。比如:从文本文件中读取文本行后再写成文本文件。这个操作可以静态方法中,方便的重用。最后,拷贝文本文件可以写成:
|
||||
|
||||
@@ -137,22 +136,21 @@ Inputs.text( source ).transferTo( Outputs.text(destination) );
|
||||
|
||||
一行代码处理了读文件、写文件、资源清理和其它零零碎碎的操作。真心的赞!`transferTo`方法会抛出`IOException`,要向用户显示`Error`可以`catch`这个异常。但实际处理这些`Error`往往是,关闭文件,把没有写成功的文件删除,而这些`Input`、`Output`已经处理好了。我们再也不需要关心文件读写的细节!
|
||||
|
||||
拦截传输过程
|
||||
---------------------------------------
|
||||
## 拦截传输过程
|
||||
|
||||
上面处理了基本的`I/O`传输,我们常常还要做些其它的事。可能要计数一下传输了多少个数据,过滤一下数据,或者是每1000条数据做一下日志,又或者要看一下正在进行什么操作。既然输入输出已经分离,这些事变成在输入输出的协调代码中简单地插入一些逻辑。大部分协调代码有类似的功能,可以放到标准的工具方法中,更方便使用。
|
||||
|
||||
第一个标准修饰器是一个过滤器。实现时我用到了`Specification`。
|
||||
|
||||
```java
|
||||
public static <T,ReceiverThrowableType extends Throwable>
|
||||
public static <T,ReceiverThrowableType extends Throwable>
|
||||
Output<T, ReceiverThrowableType> filter( final Specification<T> specification, final Output<T, ReceiverThrowableType> output)
|
||||
{
|
||||
... create an Output that filters items based on the Specification<T> ...
|
||||
}
|
||||
```
|
||||
|
||||
`Specification`如下:
|
||||
`Specification`如下:
|
||||
|
||||
```java
|
||||
interface Specification<T>
|
||||
@@ -161,7 +159,7 @@ interface Specification<T>
|
||||
}
|
||||
```
|
||||
|
||||
有了这个简单部件,我可以在传输时轻松地过滤掉那些不要出现在接收者端的数据。下面的例子删除文件中的空行:
|
||||
有了这个简单部件,我可以在传输时轻松地过滤掉那些不要出现在接收者端的数据。下面的例子删除文件中的空行:
|
||||
|
||||
```java
|
||||
File source = ...
|
||||
@@ -175,14 +173,14 @@ Inputs.text( source ).transferTo( Transforms.filter(new Specification<String>()
|
||||
}, Outputs.text(destination) );
|
||||
```
|
||||
|
||||
第二个常见的操作是把数据从一个类型映射到另一个类型。就是处理要`Input`和`Output`的数据类型不同,要有方法把输入数据类型映射成输出的数据类型。下面例子的把`String`映射成`JSONObject`,操作方法会是这个样子:
|
||||
第二个常见的操作是把数据从一个类型映射到另一个类型。就是处理要`Input`和`Output`的数据类型不同,要有方法把输入数据类型映射成输出的数据类型。下面例子的把`String`映射成`JSONObject`,操作方法会是这个样子:
|
||||
|
||||
```java
|
||||
public static <From,To,ReceiverThrowableType extends Throwable>
|
||||
Output<From, ReceiverThrowableType> map(final Function<From,To> function, final Output<To, ReceiverThrowableType> output)
|
||||
```
|
||||
|
||||
`Function`定义是:
|
||||
`Function`定义是:
|
||||
|
||||
```java
|
||||
interface Function<From, To>
|
||||
@@ -211,27 +209,25 @@ Inputs.text( source ).transferTo( Transforms.map(counter, Outputs.text(destinati
|
||||
System.out.println("Nr of lines:"+counter.getCount())
|
||||
```
|
||||
|
||||
Usage in the `Qi4j` `SPI`
|
||||
---------------------------------------
|
||||
## Usage in the `Qi4j` `SPI`
|
||||
|
||||
【译者注,这一节说具体库`Qi4j`,略过】
|
||||
|
||||
结论
|
||||
---------------------------------------
|
||||
## 结论
|
||||
|
||||
软件开发时,从一个输入到另一个输出的数据和对象的搬移很常见,可能在中间还要做些转换。通常都是用一些零散代码(`scratch`)来完成这些事,结果是代码错误和使用不当的模式。通过引入通用`I/O` `API`,恰当封闭和隔离,这个任务可以可以更轻松地以伸缩、高性能、无错误的方式完成,并且还可以在在需要额外功能时修饰实现。
|
||||
|
||||
这遍文章仅仅勾勒了这种使用方式,`API`和辅助类可以在`Qi4j Core 1.3-SNAPSHOT`中有(详见`Qi4j`的[主页](http://www.qi4j.org/))。理想状态是,在整个`Qi4j`使用中任何使用`I/O`的地方一开始按这种方式来。
|
||||
|
||||
> 【译注】`Qi4j`已经更名为`polygene`,在`Apache`上
|
||||
> - 官网 https://polygene.apache.org/
|
||||
> - GitHub仓库: https://github.com/apache/polygene-java
|
||||
> - 官网 <https://polygene.apache.org/>
|
||||
> - GitHub仓库: <https://github.com/apache/polygene-java>
|
||||
|
||||
多谢你的阅读,希望你能有所收获 :-)
|
||||
|
||||
**-EOF-**
|
||||
**_`-EOF-`_**
|
||||
|
||||
**译注:**
|
||||
## 译跋
|
||||
|
||||
原文中只给出设计的
|
||||
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
原文链接:[Subversion UI Shootout](http://onlamp.com/pub/a/onlamp/2005/03/10/svn_uis.html "Subversion UI Shootout"),2005-03-10
|
||||
译文发在:[【译】GUI & CLI Principles](http://oldratlee.com/post/2012-11-04/gui-cli-principles),2012-11-04
|
||||
|
||||
### 🍎 译序
|
||||
### 🍎 译序
|
||||
|
||||
文章[Subversion UI Shootout](http://onlamp.com/pub/a/onlamp/2005/03/10/svn_uis.html "Subversion UI Shootout")比较了多个`GUI` `SVN`工具以及命令行的优劣。
|
||||
|
||||
@@ -15,11 +15,11 @@
|
||||
PS:
|
||||
交互思考有相通的之处,下面的几篇说了不错的话题,也可以看看:
|
||||
|
||||
* [大众点评移动客户端的“轻”点评模式](http://ifredric.me/post/2012-10-31/dianping_test_2 "大众点评移动客户端的“轻”点评模式")
|
||||
* [Chrome 浏览器的哪些设计符合「Don't make me think」原则 — 知乎](http://www.zhihu.com/question/20564451 "Chrome 浏览器的哪些设计符合「Don't make me think」原则")
|
||||
你可能不知道常用的`Chrome`有哪些贴心的地方哦~
|
||||
* [PC 用户的哪些行为让你当时就震惊了? — 知乎](http://www.zhihu.com/question/20100408 "PC 用户的哪些行为让你当时就震惊了?")
|
||||
这篇里会有很多让你震惊却又会心一笑的回答。
|
||||
- [大众点评移动客户端的“轻”点评模式](http://ifredric.me/post/2012-10-31/dianping_test_2 "大众点评移动客户端的“轻”点评模式")
|
||||
- [Chrome 浏览器的哪些设计符合「Don't make me think」原则 — 知乎](http://www.zhihu.com/question/20564451 "Chrome 浏览器的哪些设计符合「Don't make me think」原则")
|
||||
你可能不知道常用的`Chrome`有哪些贴心的地方哦~
|
||||
- [PC 用户的哪些行为让你当时就震惊了? — 知乎](http://www.zhihu.com/question/20100408 "PC 用户的哪些行为让你当时就震惊了?")
|
||||
这篇里会有很多让你震惊却又会心一笑的回答。
|
||||
|
||||

|
||||
|
||||
|
||||
@@ -6,7 +6,7 @@
|
||||
提问的智慧
|
||||
====================
|
||||
|
||||

|
||||

|
||||
|
||||
**艾瑞克 · 史蒂文 · 雷蒙德(_Eric Steven Raymond_)**
|
||||
[Thyrsus Enterprises](http://www.catb.org/~esr/)
|
||||
@@ -20,7 +20,7 @@
|
||||
目录
|
||||
----------------
|
||||
|
||||
- [译文](#译文)
|
||||
- [译文](#译文)
|
||||
- [免责声明](#免责声明)
|
||||
- [引言](#引言)
|
||||
- [如何做提问前的准备](core.md#如何做提问前的准备)
|
||||
|
||||
@@ -37,13 +37,13 @@
|
||||
|
||||
在通过电邮、新闻组或论坛提技术问题以前,做以下事情:
|
||||
|
||||
1. 尝试在你准备提问论坛的历史文档中搜索答案
|
||||
2. 尝试搜索互联网以找到答案
|
||||
3. 尝试阅读手册以找到答案
|
||||
4. 尝试阅读『常见问题文档(`FAQ`)』以找到答案
|
||||
5. 尝试自己检查或试验以找到答案
|
||||
6. 尝试请教懂行的朋友以找到答案
|
||||
7. 如果你是程序员,尝试阅读源代码以找到答案
|
||||
1. 尝试在你准备提问论坛的历史文档中搜索答案
|
||||
2. 尝试搜索互联网以找到答案
|
||||
3. 尝试阅读手册以找到答案
|
||||
4. 尝试阅读『常见问题文档(`FAQ`)』以找到答案
|
||||
5. 尝试自己检查或试验以找到答案
|
||||
6. 尝试请教懂行的朋友以找到答案
|
||||
7. 如果你是程序员,尝试阅读源代码以找到答案
|
||||
|
||||
提问时,请先表明你已做了上述事情,这将有助于建立你不是寄生虫与浪费别人时间的印象。最好再表述你从中 **_学到的东西_** ,我们喜欢回答那些表现出能从答案中学习的人。
|
||||
|
||||
@@ -72,10 +72,10 @@
|
||||
|
||||
要对在哪提问留心,如果你做了下述事情,多半会被一笔勾销或被看成『失败者』:
|
||||
|
||||
* 张贴与论坛主题无关的问题
|
||||
* 在面向高级技术问题的论坛上张贴肤浅的问题,反之亦然
|
||||
* 在太多不同的新闻组同时张贴
|
||||
* 给既非熟人也没有义务解决你问题的人发送你私人的电邮
|
||||
- 张贴与论坛主题无关的问题
|
||||
- 在面向高级技术问题的论坛上张贴肤浅的问题,反之亦然
|
||||
- 在太多不同的新闻组同时张贴
|
||||
- 给既非熟人也没有义务解决你问题的人发送你私人的电邮
|
||||
|
||||
为保护通信的渠道不被无关的东西淹没,黑客会除掉那些没有找对地方的问题,你不会想让这种事落到自己头上的。
|
||||
|
||||
@@ -135,10 +135,10 @@
|
||||
|
||||
当某个项目存在开发者邮件列表时,要向列表而不是其中的个别成员提问,即使你确信他能最好地回答你的问题。查一查项目的文档和主页,找到项目的邮件列表并使用它。采用这种办法有几个很好的理由:
|
||||
|
||||
* 向一个开发者提的好问题,对整个项目组也会有益。反之,如果你认为自己的问题对整个项目组来说太愚蠢,就没有理由去去骚扰单个开发者。
|
||||
* 向列表提问可以分散开发者的负担,单个开发者(尤其是项目领导)也许太忙以至于没法回答你的问题。
|
||||
* 大多数邮件列表都要存档,那些存档将被搜索引擎索引,如果你向列表提问并得到解答,将来其它人可以通过网页搜索找到你的问题和答案,也就不用再次发问了。
|
||||
* 如果某些问题经常被问到,开发者可以利用此信息改进文档或软件本身,以使其更清楚。如果只是私下提问,就没有人能看到最常见问题的完整场景。
|
||||
- 向一个开发者提的好问题,对整个项目组也会有益。反之,如果你认为自己的问题对整个项目组来说太愚蠢,就没有理由去去骚扰单个开发者。
|
||||
- 向列表提问可以分散开发者的负担,单个开发者(尤其是项目领导)也许太忙以至于没法回答你的问题。
|
||||
- 大多数邮件列表都要存档,那些存档将被搜索引擎索引,如果你向列表提问并得到解答,将来其它人可以通过网页搜索找到你的问题和答案,也就不用再次发问了。
|
||||
- 如果某些问题经常被问到,开发者可以利用此信息改进文档或软件本身,以使其更清楚。如果只是私下提问,就没有人能看到最常见问题的完整场景。
|
||||
|
||||
如果一个项目既有 『用户』 也有『开发者』(或 『黑客』)邮件列表或论坛,而你又不摆弄那些代码,向『用户』列表或论坛提问。不要假设自己会在开发者列表中受到欢迎,那些人多半会遭受你的噪音干扰。
|
||||
|
||||
@@ -213,26 +213,26 @@
|
||||
|
||||
如果你用英语书写但它是你的第二语言,最好提醒潜在的回复者语言上可能的困难以便绕过这个问题,比如:
|
||||
|
||||
* 英语不是我的母语,请谅解拼写错误。
|
||||
* 如果您使用某某语言,请电邮/私聊我,也许我需要您的协助翻译我的问题。
|
||||
* 对于这个技术术语本身我很熟悉,但对于它的一些俚语或习惯表达方式就不太明白了。
|
||||
* 我已经同时用某某语及英语提问,如果您使用两者之一回复,我很乐意翻译。
|
||||
- 英语不是我的母语,请谅解拼写错误。
|
||||
- 如果您使用某某语言,请电邮/私聊我,也许我需要您的协助翻译我的问题。
|
||||
- 对于这个技术术语本身我很熟悉,但对于它的一些俚语或习惯表达方式就不太明白了。
|
||||
- 我已经同时用某某语及英语提问,如果您使用两者之一回复,我很乐意翻译。
|
||||
|
||||
使用易于读取且标准的文件格式发送问题
|
||||
-------------------
|
||||
|
||||
如果你人为地将问题搞得难以阅读,它多半会被忽略,人们更愿读易懂的问题,所以:
|
||||
|
||||
* 使用纯文本而不是`HTML`( [关闭`HTML`](http://www.birdhouse.org/etc/evilmail.html) 并不难)
|
||||
* 使用`MIME`附件通常没有问题,前提是真正有内容(譬如附带的源文件或补丁),而不仅仅是邮件客户端程序生成的模板(譬如只是消息内容的拷贝)。
|
||||
* 不要发送整段只是单行句子但多次折回的邮件(这使得回复部分内容非常困难)。设想你的读者是在80个字符宽的文本终端阅读邮件,设置你的行折回点小于 80 列。
|
||||
* 但是,也 **_不要_** 用任何固定列折回数据(譬如日志文件拷贝或会话记录)。数据应该原样包含,使回复者确信他们看到的是与你看到的一样的东西。
|
||||
* 在英语论坛中,不要使用`MIME`可打印字符引用编码编码([`Quoted-Printable encoding`](https://zh.wikipedia.org/wiki/Quoted-printable))发送消息。这种编码对于张贴非`ASCII`语言可能是必须的,但很多邮件程序并不支持。
|
||||
- 使用纯文本而不是`HTML`( [关闭`HTML`](http://www.birdhouse.org/etc/evilmail.html) 并不难)
|
||||
- 使用`MIME`附件通常没有问题,前提是真正有内容(譬如附带的源文件或补丁),而不仅仅是邮件客户端程序生成的模板(譬如只是消息内容的拷贝)。
|
||||
- 不要发送整段只是单行句子但多次折回的邮件(这使得回复部分内容非常困难)。设想你的读者是在80个字符宽的文本终端阅读邮件,设置你的行折回点小于 80 列。
|
||||
- 但是,也 **_不要_** 用任何固定列折回数据(譬如日志文件拷贝或会话记录)。数据应该原样包含,使回复者确信他们看到的是与你看到的一样的东西。
|
||||
- 在英语论坛中,不要使用`MIME`可打印字符引用编码编码([`Quoted-Printable encoding`](https://zh.wikipedia.org/wiki/Quoted-printable))发送消息。这种编码对于张贴非`ASCII`语言可能是必须的,但很多邮件程序并不支持。
|
||||
当它们分断时,那些文本中四处散布的 『`=20`』符号既难看也分散注意力,甚至有可能破坏内容的语意。
|
||||
* **_永远不要_** 指望黑客们阅读使用封闭的专用格式编写的文档,诸如微软公司的`Word`或`Excel`文件等。
|
||||
- **_永远不要_** 指望黑客们阅读使用封闭的专用格式编写的文档,诸如微软公司的`Word`或`Excel`文件等。
|
||||
大多数黑客对此的反应就像有人将还在冒热气的猪粪倒在你门口时你的反应一样。即使他们能够处理,也很厌恶这么做。
|
||||
* 如果你从使用视窗的电脑发送电子邮件,关闭问题颇多的微软『聪明引用』功能(在『工具』 -> 『自动纠正选项』的『输入时自动格式化』下去掉聪明引用的选框),以免在你的邮件中到处散布垃圾字符。
|
||||
* 在论坛,勿滥用『表情符号』和『`HTML`』功能(当它们提供时)。一两个表情符号通常没有问题,但花哨的彩色文本倾向于使人认为你是个无能之辈。过滥地使用表情符号、色彩和字体会使你看来像个傻笑的小姑娘。
|
||||
- 如果你从使用视窗的电脑发送电子邮件,关闭问题颇多的微软『聪明引用』功能(在『工具』 -> 『自动纠正选项』的『输入时自动格式化』下去掉聪明引用的选框),以免在你的邮件中到处散布垃圾字符。
|
||||
- 在论坛,勿滥用『表情符号』和『`HTML`』功能(当它们提供时)。一两个表情符号通常没有问题,但花哨的彩色文本倾向于使人认为你是个无能之辈。过滥地使用表情符号、色彩和字体会使你看来像个傻笑的小姑娘。
|
||||
这通常不是个好主意,除非你只是对性而不是有用的回复更有兴趣。
|
||||
|
||||
如果你使用图形用户界面的邮件客户端程序(如网景公司的`Messenger`、微软公司的`Outlook`或者其它类似的),注意它们的缺省配置不一定满足这些要求。
|
||||
@@ -241,12 +241,12 @@
|
||||
描述问题应准确且有内容
|
||||
-------------------
|
||||
|
||||
* 仔细、清楚地描述问题的症状
|
||||
* 描述问题发生的环境(主机、操作系统、应用程序,任何相关的),提供销售商的发行版和版本号(如:『`Fedora Core 7`』、『`Slackware 9.1`』等)
|
||||
* 描述提问前做过的研究及其理解。
|
||||
* 描述提问前为确定问题而采取的诊断步骤。
|
||||
* 描述最近对计算机或软件配置的任何相关改变。
|
||||
* 如果可能,提供在可控环境下重现问题的方法。
|
||||
- 仔细、清楚地描述问题的症状
|
||||
- 描述问题发生的环境(主机、操作系统、应用程序,任何相关的),提供销售商的发行版和版本号(如:『`Fedora Core 7`』、『`Slackware 9.1`』等)
|
||||
- 描述提问前做过的研究及其理解。
|
||||
- 描述提问前为确定问题而采取的诊断步骤。
|
||||
- 描述最近对计算机或软件配置的任何相关改变。
|
||||
- 如果可能,提供在可控环境下重现问题的方法。
|
||||
|
||||
尽最大努力预测黑客会提到的问题,并提前备好答案。
|
||||
|
||||
|
||||
@@ -78,9 +78,10 @@
|
||||
我的{程序、配置、`SQL`语句}不运行了
|
||||
**答:**
|
||||
这不是一个问题,我也没有兴趣去猜你有什么问题 —— 我有更要紧的事要做。看到这种东西,我的反应一般如下:
|
||||
* 你还有什么补充吗?
|
||||
* 噢,太糟了,希望你能搞定。
|
||||
* 这跟我究竟有什么关系?
|
||||
|
||||
- 你还有什么补充吗?
|
||||
- 噢,太糟了,希望你能搞定。
|
||||
- 这跟我究竟有什么关系?
|
||||
|
||||
<a id="id266052"></a>
|
||||
**问:**
|
||||
|
||||
@@ -42,9 +42,9 @@
|
||||
|
||||
设计我们实验设施的目标是:_更多_、_更好_、_更快_。
|
||||
|
||||
* **更多**:我们需要能同时进行多个实验的可扩展性。但是我们也需要灵活性:不同的实验需要不同的配置和不同的流量来衡量实验的统计意义上的效果显著性。有些实验只需要修改流量的一个子集,比如只是日语的流量,并需要取一个合理的流量规模。其它的实验有可能需要修改所有的流量,并对指标造成很大影响,这种才可以在小流量上进行测试。
|
||||
* **更好**:不合理的实验是不应该让它在线上流量进行的。合理的但是很差的实验(比如,有`Bug`的实验或是无意中产生的很差的实验结果)都应该能很快的被捕获并且停止它的进行。标准化的标价指标可以让所有的实验进行公平的比较:比如在计算`CTR`指标的时间,两个实验应该用相同的过滤器去掉爬虫流量。
|
||||
* **更快**:能够很容易并且很快地建立一个实验。容易到非工程师不需要写代码就可以创建一个实验。评价指标应该很快的被统计出来,以便分析。简单的迭代可以很快速地进行。理想状态是,实验系统不仅支持实验,并且可以控制放量,比如,以一种系统的和容易理解的方式对实验进行放量。
|
||||
- **更多**:我们需要能同时进行多个实验的可扩展性。但是我们也需要灵活性:不同的实验需要不同的配置和不同的流量来衡量实验的统计意义上的效果显著性。有些实验只需要修改流量的一个子集,比如只是日语的流量,并需要取一个合理的流量规模。其它的实验有可能需要修改所有的流量,并对指标造成很大影响,这种才可以在小流量上进行测试。
|
||||
- **更好**:不合理的实验是不应该让它在线上流量进行的。合理的但是很差的实验(比如,有`Bug`的实验或是无意中产生的很差的实验结果)都应该能很快的被捕获并且停止它的进行。标准化的标价指标可以让所有的实验进行公平的比较:比如在计算`CTR`指标的时间,两个实验应该用相同的过滤器去掉爬虫流量。
|
||||
- **更快**:能够很容易并且很快地建立一个实验。容易到非工程师不需要写代码就可以创建一个实验。评价指标应该很快的被统计出来,以便分析。简单的迭代可以很快速地进行。理想状态是,实验系统不仅支持实验,并且可以控制放量,比如,以一种系统的和容易理解的方式对实验进行放量。
|
||||
|
||||
为了达到这些设计的目标,我们不仅需要实验设施来进行更多的实验,并且需要一些工具和指导过程来支持更多和更快的实验。
|
||||
|
||||
@@ -85,14 +85,14 @@
|
||||
|
||||
事实上,我们设计的更加灵活,我们不止是将参数划分子集,再将子集与层相关联。为了解释灵活性,我们引入了一些定义。在流量和系统参数的语境下,我们有三个关键的概念:
|
||||
|
||||
* **域**是指流量的一个划分(一部分流量的意思)。
|
||||
* **层**是指系统参数的一个子集。
|
||||
* **实验**是指在一个流量划分上,进行零个或多个参数的修改,并最后改变请求处理的过程。
|
||||
- **域**是指流量的一个划分(一部分流量的意思)。
|
||||
- **层**是指系统参数的一个子集。
|
||||
- **实验**是指在一个流量划分上,进行零个或多个参数的修改,并最后改变请求处理的过程。
|
||||
|
||||
域和层可以相互嵌套。域中包含层。层中包含实验,层中也可以包含域。在一个层中嵌套域可以使这一层中的参数在嵌套域中进行进一步划分。开始时,我们有默认的域和层,它有包含所有的流量和参数,在默认域和层中,比如我们可以:
|
||||
|
||||
* 简单地将参数分为三层(图2a),这种情况下,每个请求最多只会同时在三个实验中,每层一个,每个实验只能修改相应层的参数。
|
||||
* 我们可以先将流量分为两个域,一个域只有一个单一层(非重叠域),和一个有三个层的重叠域(见图2b),在这种情况下,每个请求会分到非重叠域或是重叠域。请求只能在非重叠域或重叠域其中之一。如果请求在重叠域,那么请求最多在一个实验中(这个实验可以改变参数集合中的任意参数的值),如果请求在重叠域,那么请求最多在三个实验中,每层一个实验。并且对于每个实验,只能使用对应层的参数。
|
||||
- 简单地将参数分为三层(图2a),这种情况下,每个请求最多只会同时在三个实验中,每层一个,每个实验只能修改相应层的参数。
|
||||
- 我们可以先将流量分为两个域,一个域只有一个单一层(非重叠域),和一个有三个层的重叠域(见图2b),在这种情况下,每个请求会分到非重叠域或是重叠域。请求只能在非重叠域或重叠域其中之一。如果请求在重叠域,那么请求最多在一个实验中(这个实验可以改变参数集合中的任意参数的值),如果请求在重叠域,那么请求最多在三个实验中,每层一个实验。并且对于每个实验,只能使用对应层的参数。
|
||||
|
||||
<img src="figure-02.png" width="512" />
|
||||
|
||||
@@ -106,9 +106,9 @@
|
||||
|
||||
另一个概念是**发布层**(`Launch layers`),发布层与前面介绍的实验层有下面区别:
|
||||
|
||||
* 发布层总是在默认域中(比如,它们有全部流量)。
|
||||
* 发布层是对参数的一个独立划分,比如,一个参数最多只能同时在一个发布层和最多一个正常层中(一个域中)。
|
||||
* 为了让发布层和正常层的重复参数配合起来。在发布层中的实验有着稍有不同的语法。特别是,在发布层的实验会为覆盖参数的默认值,作为新的默认值,换言之,如果没有正常实验层的实验覆盖了默认参数,那么在发布层的行为就像一个普通的实验,但如果实验层的实验覆盖了默认值,那么实验就会用这个覆盖的值,而不是系统的默认值,或是发布层实验中的参数值。
|
||||
- 发布层总是在默认域中(比如,它们有全部流量)。
|
||||
- 发布层是对参数的一个独立划分,比如,一个参数最多只能同时在一个发布层和最多一个正常层中(一个域中)。
|
||||
- 为了让发布层和正常层的重复参数配合起来。在发布层中的实验有着稍有不同的语法。特别是,在发布层的实验会为覆盖参数的默认值,作为新的默认值,换言之,如果没有正常实验层的实验覆盖了默认参数,那么在发布层的行为就像一个普通的实验,但如果实验层的实验覆盖了默认值,那么实验就会用这个覆盖的值,而不是系统的默认值,或是发布层实验中的参数值。
|
||||
|
||||
发布层的示例在图2c、2d中,通过发布层,我们能以一种标准通用的方式逐步灰度最终全量一个实验策略,且可以跟踪灰度过程中实验效果变化。 通常情况下,每有一个新特性要开始全量时都需要新建一个发布层,当这个新特性最终完成全量时,再将相应的发布层删除。并且因为发布层实验的流量一般都比较大,所以它们可以用于测试特性之间的相互影响,虽然理论上我们可以测试正常实验层的特性相互影响(比如,如果参数在同一层,我们可以手工设置创建实验,如果参数在不同层,我们观察实验的交集流量),但因为在正常层中,实验流量比较少,交集比较小,所以相互影响很难检测。
|
||||
|
||||
@@ -129,11 +129,11 @@
|
||||
|
||||
在这个设施下,一个特性的评估和发布过程是类似如下过程的:
|
||||
|
||||
* 在合适的模块中,实现新的特性(包括`code review`、二进制推送、设置默认参数等等,和标准的工程实践一样)。
|
||||
* 创建一个灰度实验(通过数据推送方式),以保证特性可以正常工作,如果不能正常工作,那么可能就要重写代码修复这个问题。
|
||||
* 创建一个实验或是一组实验(通过数据推送的方式)来评估特性。注意配置实验涉及指定分配类型和相关的分配参数(比如:`cookie`取模),分配条件,和特性相关的参数。
|
||||
* 评估实验指标。根据实验结果,判断是否要进行新一轮的实验,即通过修改或创建新的实验,或甚至修改代码从根本上改变特性。
|
||||
* 如果特性可以发布,就进入发布过程:创建一个新的发布层和发布层实验,逐步的放量这个实验,并最终删除发布完的发布层,然后将发布层实验的相关参数设为系统默认参数。
|
||||
- 在合适的模块中,实现新的特性(包括`code review`、二进制推送、设置默认参数等等,和标准的工程实践一样)。
|
||||
- 创建一个灰度实验(通过数据推送方式),以保证特性可以正常工作,如果不能正常工作,那么可能就要重写代码修复这个问题。
|
||||
- 创建一个实验或是一组实验(通过数据推送的方式)来评估特性。注意配置实验涉及指定分配类型和相关的分配参数(比如:`cookie`取模),分配条件,和特性相关的参数。
|
||||
- 评估实验指标。根据实验结果,判断是否要进行新一轮的实验,即通过修改或创建新的实验,或甚至修改代码从根本上改变特性。
|
||||
- 如果特性可以发布,就进入发布过程:创建一个新的发布层和发布层实验,逐步的放量这个实验,并最终删除发布完的发布层,然后将发布层实验的相关参数设为系统默认参数。
|
||||
|
||||
# 5. 工具与流程
|
||||
|
||||
@@ -141,8 +141,8 @@
|
||||
|
||||
## 5.1 工具
|
||||
|
||||
* **数据文件检查:** 数据文件的其一优势是它们可以被自动检查错误,这可以避免一些不合理的实验运行。我们会自动检查法语错误(所有的必填字段都有并且合法),一致性和约束错误(比如,`id`的唯一性,根据所有的参数判断是否实验在正确的层,是否这一层有足够的流量来支持实验,流量约束检查,如果实验要求的流量已经被另一个实验使用了,等等,注意当可用的分配条件集合变大时,这些检查就变的复杂了),和基本的实验设置检查(是否实验有对比实验,并且对比实验在相同的层,是否对比实验与实验的流量分配方式和规模一致,等等)。
|
||||
* **实时监控:** 我们用实时监控来检测基本的指标(比如`CTR`),我们通过实时监控尽快地发现某个实验是不正常的,实验者可以设置监控指标的期望值区间(也有这些指标的默认波动区间),如果监控指标超出了期望的波动区间,那么会触发自动告警,然后实验者可以修改期望区间或停止他们的实验,或调整它们的实验参数值,但它允许实验者可以激进地对于可能的潜在的变化进行测试,因为错误或预期之外的影响会被很快检测到。
|
||||
- **数据文件检查:** 数据文件的其一优势是它们可以被自动检查错误,这可以避免一些不合理的实验运行。我们会自动检查法语错误(所有的必填字段都有并且合法),一致性和约束错误(比如,`id`的唯一性,根据所有的参数判断是否实验在正确的层,是否这一层有足够的流量来支持实验,流量约束检查,如果实验要求的流量已经被另一个实验使用了,等等,注意当可用的分配条件集合变大时,这些检查就变的复杂了),和基本的实验设置检查(是否实验有对比实验,并且对比实验在相同的层,是否对比实验与实验的流量分配方式和规模一致,等等)。
|
||||
- **实时监控:** 我们用实时监控来检测基本的指标(比如`CTR`),我们通过实时监控尽快地发现某个实验是不正常的,实验者可以设置监控指标的期望值区间(也有这些指标的默认波动区间),如果监控指标超出了期望的波动区间,那么会触发自动告警,然后实验者可以修改期望区间或停止他们的实验,或调整它们的实验参数值,但它允许实验者可以激进地对于可能的潜在的变化进行测试,因为错误或预期之外的影响会被很快检测到。
|
||||
|
||||
## 5.2 实验设计与样本量
|
||||
|
||||
@@ -158,9 +158,9 @@
|
||||
|
||||
在工程实践中,我们主要关注 <img src="http://chart.googleapis.com/chart?cht=tx&chf=bg,s,00000000&chl=%5Ctext%7Bqueries%7D_%7B%5Ctext%7Bcontrol%7D%7D" style="border:none;" alt="\text{queries}_{\text{control}}" /> 和 <img src="http://chart.googleapis.com/chart?cht=tx&chf=bg,s,00000000&chl=%5Ctext%7Bqueries%7D_%7B%5Ctext%7Bexperiment%7D%7D" style="border:none;" /> ,但要通过 <img src="http://chart.googleapis.com/chart?cht=tx&chf=bg,s,00000000&chl=N" style="border:none;" alt="N" /> 个和才能影响相关的实验指标,为了正确确定 <img src="http://chart.googleapis.com/chart?cht=tx&chf=bg,s,00000000&chl=N" style="border:none;" alt="N" /> 值,我们需要知道:
|
||||
|
||||
* 实验所关注的指标是什么。
|
||||
* 对每个指标,我们想检测实验改变的敏感度(<img src="http://chart.googleapis.com/chart?cht=tx&chf=bg,s,00000000&chl=%5Ctheta%20" style="border:none;" alt="\theta" />)值是什么。比如,实验者想检测到2%的点击率变化。
|
||||
* 对每个指标,一个抽样单元(<img src="http://chart.googleapis.com/chart?cht=tx&chf=bg,s,00000000&chl=N%3D1" style="border:none;" alt="N=1" />)样本标准误差是(<img src="http://chart.googleapis.com/chart?cht=tx&chf=bg,s,00000000&chl=s" style="border:none;" alt="s" />),实验大小为 <img src="http://chart.googleapis.com/chart?cht=tx&chf=bg,s,00000000&chl=N" style="border:none;" alt="N" /> 的标准误差为 <img src="http://chart.googleapis.com/chart?cht=tx&chf=bg,s,00000000&chl=s%2F%5Csqrt%7BN%7D" style="border:none;" alt="s/\sqrt{N}" />。
|
||||
- 实验所关注的指标是什么。
|
||||
- 对每个指标,我们想检测实验改变的敏感度(<img src="http://chart.googleapis.com/chart?cht=tx&chf=bg,s,00000000&chl=%5Ctheta%20" style="border:none;" alt="\theta" />)值是什么。比如,实验者想检测到2%的点击率变化。
|
||||
- 对每个指标,一个抽样单元(<img src="http://chart.googleapis.com/chart?cht=tx&chf=bg,s,00000000&chl=N%3D1" style="border:none;" alt="N=1" />)样本标准误差是(<img src="http://chart.googleapis.com/chart?cht=tx&chf=bg,s,00000000&chl=s" style="border:none;" alt="s" />),实验大小为 <img src="http://chart.googleapis.com/chart?cht=tx&chf=bg,s,00000000&chl=N" style="border:none;" alt="N" /> 的标准误差为 <img src="http://chart.googleapis.com/chart?cht=tx&chf=bg,s,00000000&chl=s%2F%5Csqrt%7BN%7D" style="border:none;" alt="s/\sqrt{N}" />。
|
||||
|
||||
_Kohavi_ 假设实验与对照实验有相同的大小,比如 <img src="http://chart.googleapis.com/chart?cht=tx&chf=bg,s,00000000&chl=%5Ctext%7Bqueries%7D_%7B%5Ctext%7Bexperiment%7D%7D%3D2N" style="border:none;" alt="\text{queries}_{\text{experiment}}=2N" /> ,那么必须 <img src="http://chart.googleapis.com/chart?cht=tx&chf=bg,s,00000000&chl=2N" style="border:none;" alt="2N" /> 大于等于 <img src="http://chart.googleapis.com/chart?cht=tx&chf=bg,s,00000000&chl=16(s%2F%5Ctheta)%5E2" style="border:none;" alt="16(s/\theta)^2" /> 才能满足最小变化检测需求,16这个值是由置信度( <img src="http://chart.googleapis.com/chart?cht=tx&chf=bg,s,00000000&chl=1-%5Calpha" style="border:none;" alt="1-\alpha" /> ,通常为95%)和期望的统计功效( <img src="http://chart.googleapis.com/chart?cht=tx&chf=bg,s,00000000&chl=1-%5Cbeta" style="border:none;" alt="1-\beta" /> ,通常为80%)决定的。
|
||||
|
||||
@@ -196,10 +196,10 @@ _Kohavi_ 假设实验与对照实验有相同的大小,比如 <img src="http:/
|
||||
|
||||
实验除了正确性和完备性,对一个实验分析工具的其它重要设计目标包括:
|
||||
|
||||
* 正确地计算和显示置信区间:实验者需要知道是否他的实验仅是没有得到足够的流量(置信区间太宽),或是是否观察到的变化是统计显著的。我们研究了很多种计算准确置信区间的方法,虽然无法完整地讨论已经超出了本文范围,仅说明一下我们考虑了`delta`方法和其它的经验方法来计算置信区间:将实验分成几个子集,从这些子集上统计方差,并注意,一定要观察多个实验指标和实验,因为一些指标值会随机显示为显著,所以一定要多检查。
|
||||
* 一个好的`UI`,`UI`必须是易用的,并是易于理解的。图形化是会有所帮助的,如果要聚合的效果在一定时期内是致的,即使是简单的走势图也能对可视化有所帮助。`UI`也应提示不合理的比较(比如,比较两个不同层的实验),并且`UI`应该方便地更改对比的实验,或对比的时期等等。
|
||||
* 支持划分,聚合后的数值常会有误导性,比如导致指标改变的原因也许并不是实验(比如,`CTR`改变),而是因为一个混合的变化(比如,更多的商业搜索词)。正如 _Kohavi_ 所言[4],辛普森悖论的观察与理解是很重要的。
|
||||
* 扩展性,它必须能方便地添加用户自定义的指标和划分,特别是对新特性,已经存在的指标集合和划分可能是不够的。
|
||||
- 正确地计算和显示置信区间:实验者需要知道是否他的实验仅是没有得到足够的流量(置信区间太宽),或是是否观察到的变化是统计显著的。我们研究了很多种计算准确置信区间的方法,虽然无法完整地讨论已经超出了本文范围,仅说明一下我们考虑了`delta`方法和其它的经验方法来计算置信区间:将实验分成几个子集,从这些子集上统计方差,并注意,一定要观察多个实验指标和实验,因为一些指标值会随机显示为显著,所以一定要多检查。
|
||||
- 一个好的`UI`,`UI`必须是易用的,并是易于理解的。图形化是会有所帮助的,如果要聚合的效果在一定时期内是致的,即使是简单的走势图也能对可视化有所帮助。`UI`也应提示不合理的比较(比如,比较两个不同层的实验),并且`UI`应该方便地更改对比的实验,或对比的时期等等。
|
||||
- 支持划分,聚合后的数值常会有误导性,比如导致指标改变的原因也许并不是实验(比如,`CTR`改变),而是因为一个混合的变化(比如,更多的商业搜索词)。正如 _Kohavi_ 所言[4],辛普森悖论的观察与理解是很重要的。
|
||||
- 扩展性,它必须能方便地添加用户自定义的指标和划分,特别是对新特性,已经存在的指标集合和划分可能是不够的。
|
||||
|
||||
只有一个工具提供实验准确的指标意味着我们有唯一的一致性实现,它使用相同的过滤器(比如,移除潜在的爬虫流量和垃圾流量),这样,不同的团队之间就可的`CTR`值就具有了可比较性。一个唯一的工具也更高效,因为计算会一次完成后,并呈现给实验者们,而不是每个实验者进行他们自己的计算。
|
||||
|
||||
@@ -211,12 +211,12 @@ _Kohavi_ 假设实验与对照实验有相同的大小,比如 <img src="http:/
|
||||
|
||||
第一个过程我们称之为实验委员会,它包含一组工程师,他们会审核实验者在做实验前提交的一个轻量级的`checklist`,`checklist`中问题包括:
|
||||
|
||||
* 基本的实验特性(比如,实验测试什么?它们的假设是什么?)
|
||||
* 实验的建立(比如,要修改哪些参数,每个实验或实验集合分别要测试的是什么?在哪一层?)
|
||||
* 实验的流量分配和触发条件(比如,使用什么分配类型和什么分配条件,在多大比例的流量触发实验)
|
||||
* 实验分析(比如,关注哪个指标?实验者要检测的指标敏感度是什么?)
|
||||
* 实验规模和时间跨度(即保证,给定一定的流量,实验是有足够的统计量来检测指标敏感度)
|
||||
* 实验设计(比如,是否要用预时期和后时期来保证,是否反事实日志正确被记录等等)
|
||||
- 基本的实验特性(比如,实验测试什么?它们的假设是什么?)
|
||||
- 实验的建立(比如,要修改哪些参数,每个实验或实验集合分别要测试的是什么?在哪一层?)
|
||||
- 实验的流量分配和触发条件(比如,使用什么分配类型和什么分配条件,在多大比例的流量触发实验)
|
||||
- 实验分析(比如,关注哪个指标?实验者要检测的指标敏感度是什么?)
|
||||
- 实验规模和时间跨度(即保证,给定一定的流量,实验是有足够的统计量来检测指标敏感度)
|
||||
- 实验设计(比如,是否要用预时期和后时期来保证,是否反事实日志正确被记录等等)
|
||||
|
||||
初次使用的实验者会通过这些问题学习合理的实验设计和实验样本量,并了解实施一个实验背后的技术细节。有经验的实验者仍会发现`checklist`仍是有用的。不止于此,这个方法可以将所产生的更好的实验实践传播出来(比如,产生了新的工具来促进实验,产生了新的评价指标,等等),这个`checklist`是一个`Web`应用,`Web`应用对于存档和教导都是有用的,教导作用体现在实验者可以阅读以往的`checklist`来理解相关信息。
|
||||
|
||||
@@ -224,9 +224,9 @@ _Kohavi_ 假设实验与对照实验有相同的大小,比如 <img src="http:/
|
||||
|
||||
另一个过程是讨论会,实验者们带着他们的实验结果与专家进行讨论,讨论的目标是:
|
||||
|
||||
* 保证实验的结果是有效的。在有些时候,即使有实验委员会,但在实际的实验上出错了,或是有一些意外发生,在这些情况中,讨论会中的讨论就像是一个调试(`debugging`)的过程,而对涉及的应用、日志、实验设施、指标和分析工具都有整体了解的专家是解决问题的关键。
|
||||
* 有了有效的结果后,要保证对指标集合做整体的观察,以理解实验结果到底如何,其它划分数据的方法或是改变指标也许可以更进一步理解实验的影响。一些实验很复杂,需要实验者追踪地进行几次。
|
||||
* 有了完整的结果集合,讨论并决定整个实验是一个正影响或负影响的用户体验,有了决定后,决策者可用这个数据(结合策略和战略信息)来决定是否要发布这个实验,或提出可能的改进建议,或是放弃。
|
||||
- 保证实验的结果是有效的。在有些时候,即使有实验委员会,但在实际的实验上出错了,或是有一些意外发生,在这些情况中,讨论会中的讨论就像是一个调试(`debugging`)的过程,而对涉及的应用、日志、实验设施、指标和分析工具都有整体了解的专家是解决问题的关键。
|
||||
- 有了有效的结果后,要保证对指标集合做整体的观察,以理解实验结果到底如何,其它划分数据的方法或是改变指标也许可以更进一步理解实验的影响。一些实验很复杂,需要实验者追踪地进行几次。
|
||||
- 有了完整的结果集合,讨论并决定整个实验是一个正影响或负影响的用户体验,有了决定后,决策者可用这个数据(结合策略和战略信息)来决定是否要发布这个实验,或提出可能的改进建议,或是放弃。
|
||||
|
||||
讨论会对实验者是一个学习如何解读实验结果的有益之所,有经验的实验者通常不会犯以前犯过的错误,并可以预期要得到完全理解的实验结果,需要什么数据。讨论是开放的,将来要进行实验的人,可以参加以了解运行一个实验需要了解什么。实验都会记录,我们就有了一个知识库。
|
||||
|
||||
@@ -245,10 +245,10 @@ _Kohavi_ 假设实验与对照实验有相同的大小,比如 <img src="http:/
|
||||
|
||||
另一个衡量我们整体系统工具和系统的指标是判断是否比以前运行实验更好,于此我们仅有耳闻,没有实际的数据,但我们是实验委员会和讨论组的成员,我们见过这个系统发布前后的许多实验情况,我们观察的结论是:
|
||||
|
||||
* 错误配置的实验变少了,尽管我们仍偶尔会遇到日志的问题(反事实)或是诡异的错误/失败情况。
|
||||
* 被遗忘的实验变少了(比如,有进行了实验,却之后忘记了分析实验)。
|
||||
* 『究竟你是用什么指标衡量`CTR`的』或是『你用的是什么过滤器』的讨论减少了,有一个权威的分析工具,讨论的重点现在仅在于对指标进行解释,而不是确保指标的定义和计算都是合理的。
|
||||
* 更好的合理性检查,比如有预时期来确保实验所用的流量是没有问题的。
|
||||
- 错误配置的实验变少了,尽管我们仍偶尔会遇到日志的问题(反事实)或是诡异的错误/失败情况。
|
||||
- 被遗忘的实验变少了(比如,有进行了实验,却之后忘记了分析实验)。
|
||||
- 『究竟你是用什么指标衡量`CTR`的』或是『你用的是什么过滤器』的讨论减少了,有一个权威的分析工具,讨论的重点现在仅在于对指标进行解释,而不是确保指标的定义和计算都是合理的。
|
||||
- 更好的合理性检查,比如有预时期来确保实验所用的流量是没有问题的。
|
||||
|
||||
显然理想的结果是上述问题都不存在,但是考虑到我们有更多的实验者,而上述问题即在下降,这已经是一个不错的结果。
|
||||
|
||||
@@ -256,10 +256,10 @@ _Kohavi_ 假设实验与对照实验有相同的大小,比如 <img src="http:/
|
||||
|
||||
最后的一个衡量我们系统成功的指标是我们是否最终更快地得到数据,并更快地做出决策,对于速度,我们还是没有具体数据,但我们可以讨论对实验速度的观察,实验可以分解为下面几个阶段:
|
||||
|
||||
* 实现一个新特性并对它进行测试,这阶段现在是最慢的,所以我们还建立了其它工具(不在本文范围)来加速创建和测试原型(比如,将下面两个步骤分离:建立可实验的版本和正式可发布版)
|
||||
* 对这个实现的特性创建一个新的实验,这个阶段要花几分钟或几小时来创建,取决于参数的复杂性,和一个少的可以忽略的提交前的检查时间(几秒到几分钟),创建时的`review`时间同样很短,数据推送的时间取决于二进制,时间在1-2小时(包括灰度测试时间)到半天。
|
||||
* 运行实验的速度取决于实验的规模和实验要运行多久才能得到想要的统计显著值。我们在实验开始后的数小时就通常就可以对实验的效果有大致的了解。实验总的时间跨度取决于:实验所需要的迭代次数、规模和紧急性,等等。
|
||||
* 分析实验的时间长短也不一定。在很多情况下,不需要自定义的分析方法,或是只需要对分析工具进行很小的扩展。在这些情况中,分析速度通常很快(数天)。但在其它情况下,需要自定义的分析方法分析的时间的长度就不一定了。
|
||||
- 实现一个新特性并对它进行测试,这阶段现在是最慢的,所以我们还建立了其它工具(不在本文范围)来加速创建和测试原型(比如,将下面两个步骤分离:建立可实验的版本和正式可发布版)
|
||||
- 对这个实现的特性创建一个新的实验,这个阶段要花几分钟或几小时来创建,取决于参数的复杂性,和一个少的可以忽略的提交前的检查时间(几秒到几分钟),创建时的`review`时间同样很短,数据推送的时间取决于二进制,时间在1-2小时(包括灰度测试时间)到半天。
|
||||
- 运行实验的速度取决于实验的规模和实验要运行多久才能得到想要的统计显著值。我们在实验开始后的数小时就通常就可以对实验的效果有大致的了解。实验总的时间跨度取决于:实验所需要的迭代次数、规模和紧急性,等等。
|
||||
- 分析实验的时间长短也不一定。在很多情况下,不需要自定义的分析方法,或是只需要对分析工具进行很小的扩展。在这些情况中,分析速度通常很快(数天)。但在其它情况下,需要自定义的分析方法分析的时间的长度就不一定了。
|
||||
|
||||
概括才言,当前的耗时点有:实现一个实验,在预时期的运行时间、自定义分析。这些耗时点是我们努力解决的点。
|
||||
|
||||
@@ -269,10 +269,10 @@ _Kohavi_ 假设实验与对照实验有相同的大小,比如 <img src="http:/
|
||||
|
||||
下面是几个我们要继续改进我们实设设施的方向,包括:
|
||||
|
||||
* 提供加速实验新特性的方法和推动一些特别的实验(不是通过参数表达的实验)。
|
||||
* 突破一个实验参数被限制到一个层的规定。特别是,对于数值参数,我们添加了运算操作(比如,乘、加),它们是可传递的,也就是可组合的。有了这些操作符,我们可以在多个层用同一参数,只要实验都只是指定对默认值的操作,而不是覆盖默认值。
|
||||
* 有的时候我们需要在很小的流量切片上运行实验,比如小语种上(比如乌兹别克语、斯瓦希里语)。在这样的小的流量切片上进行实验,通常很难在一个合理的时间范围内有足够大的规模得到统计意义上显著的结果。
|
||||
* 继续提供更多新的分配条件(和相关的验证以保证健壮性)以支持更有效地利用实验空间,等等。
|
||||
- 提供加速实验新特性的方法和推动一些特别的实验(不是通过参数表达的实验)。
|
||||
- 突破一个实验参数被限制到一个层的规定。特别是,对于数值参数,我们添加了运算操作(比如,乘、加),它们是可传递的,也就是可组合的。有了这些操作符,我们可以在多个层用同一参数,只要实验都只是指定对默认值的操作,而不是覆盖默认值。
|
||||
- 有的时候我们需要在很小的流量切片上运行实验,比如小语种上(比如乌兹别克语、斯瓦希里语)。在这样的小的流量切片上进行实验,通常很难在一个合理的时间范围内有足够大的规模得到统计意义上显著的结果。
|
||||
- 继续提供更多新的分配条件(和相关的验证以保证健壮性)以支持更有效地利用实验空间,等等。
|
||||
|
||||
> 【译注】:斯瓦希里语是当今非洲最常用的语言之一。
|
||||
|
||||
@@ -282,14 +282,14 @@ _Kohavi_ 假设实验与对照实验有相同的大小,比如 <img src="http:/
|
||||
|
||||
# 8. 参考资料
|
||||
|
||||
* [1] D. Agarwal, A. Broder, D. Chakrabarti, D. Diklic, V. Josifovski, and M. Sayyadian. Estimating rates of rare events at multiple resolutions. In **_Proceedings of the ACM Conference on Knowledge Discovery and Data Mining (KDD)_**, 2007.
|
||||
* [2] W. G. Cochran. **_Sampling Techniques_**. Wiley, 1977.
|
||||
* [3] D. Cox and N. Reid. The theory of the design of experiments, 2000.
|
||||
* [4] T. Crook, B. Frasca, R. Kohavi, and R. Longbotham. Seven pitfalls to avoid when running controlled experiments on the web. Microsoft white paper, March 2008\. http://exp-platform.com/Documents/ExPpitfalls.pdf.
|
||||
* [5] Google. Google website optimizer. http://www.google.com/analytics/siteopt.
|
||||
* [6] T. Joachims. Optimizing search engines using clickthrough data. In **_Proceedings of the ACM Conference on Knowledge Discovery and Data Mining (KDD)_**, 2002.
|
||||
* [7] R. Kohavi, R. Longbotham, D. Sommerfield, and R. M. Henne. Controlled experiments on the web: Survey and practical guide. **_Data Mining and Knowledge Discovery_**, 18, no. 1:140–181, July 2008.
|
||||
* [8] M. Krieger. Wrap up & experimentation: Cs147l lecture, 12 2009. http://hci.stanford.edu/courses/cs147/lab/slides/08-experimentation.pdf .
|
||||
* [9] Microsoft. Microsoft’s experimentation platform. http://exp-platform.com/default.aspx.
|
||||
* [10] M. Richardson, E. Dominowska, and R. Ragno. Predicting clicks: Estimating the click-through rate for new ads. In **_Proceedings of the 16th International World Wide Web Conference_**, 2007.
|
||||
* [11] L. Wasserman. All of Statistics: **_A Concise Course in Statistical Inference_**. Springer Texts, 2004.
|
||||
- [1] D. Agarwal, A. Broder, D. Chakrabarti, D. Diklic, V. Josifovski, and M. Sayyadian. Estimating rates of rare events at multiple resolutions. In **_Proceedings of the ACM Conference on Knowledge Discovery and Data Mining (KDD)_**, 2007.
|
||||
- [2] W. G. Cochran. **_Sampling Techniques_**. Wiley, 1977.
|
||||
- [3] D. Cox and N. Reid. The theory of the design of experiments, 2000.
|
||||
- [4] T. Crook, B. Frasca, R. Kohavi, and R. Longbotham. Seven pitfalls to avoid when running controlled experiments on the web. Microsoft white paper, March 2008\. <http://exp-platform.com/Documents/ExPpitfalls.pdf>.
|
||||
- [5] Google. Google website optimizer. <http://www.google.com/analytics/siteopt>.
|
||||
- [6] T. Joachims. Optimizing search engines using clickthrough data. In **_Proceedings of the ACM Conference on Knowledge Discovery and Data Mining (KDD)_**, 2002.
|
||||
- [7] R. Kohavi, R. Longbotham, D. Sommerfield, and R. M. Henne. Controlled experiments on the web: Survey and practical guide. **_Data Mining and Knowledge Discovery_**, 18, no. 1:140–181, July 2008.
|
||||
- [8] M. Krieger. Wrap up & experimentation: Cs147l lecture, 12 2009. <http://hci.stanford.edu/courses/cs147/lab/slides/08-experimentation.pdf>.
|
||||
- [9] Microsoft. Microsoft’s experimentation platform. <http://exp-platform.com/default.aspx>.
|
||||
- [10] M. Richardson, E. Dominowska, and R. Ragno. Predicting clicks: Estimating the click-through rate for new ads. In **_Proceedings of the 16th International World Wide Web Conference_**, 2007.
|
||||
- [11] L. Wasserman. All of Statistics: **_A Concise Course in Statistical Inference_**. Springer Texts, 2004.
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
`Python` Philosophy原文及相关说明: [http://www.c2.com/cgi/wiki?PythonPhilosophy](http://www.c2.com/cgi/wiki?PythonPhilosophy)
|
||||
`Python` Philosophy原文及相关说明: [http://www.c2.com/cgi/wiki?PythonPhilosophy](http://www.c2.com/cgi/wiki?PythonPhilosophy)
|
||||
译文发在:[`Python` Philosophy(`Python`哲学)翻译及简析](http://oldratlee.com/147/tech/python/python-philosophy.html),2010-09-28
|
||||
|
||||
# `Python` Philosophy(`Python`哲学)翻译及简析
|
||||
@@ -35,7 +35,7 @@
|
||||
1. 面对二义性情况时,要拒绝任何猜的诱惑。
|
||||
1. 一件事应该一种做法 —— 并且宁愿只有一种做法 —— 一种显而易见的做法。
|
||||
- 尽管在刚开始的时候这个做法可能不是那么显而易见,毕竟你不是荷兰人。 <sup>**_[5]_**</sup>
|
||||
1. 『现在』优于『决不』。 <sup>**_[6]_**</sup>
|
||||
1. 『现在』优于『决不』。 <sup>**_[6]_**</sup>
|
||||
- 尽管『决不』常常优于『**_马上_**』。 <sup>**_[7]_**</sup>
|
||||
1. 如果一个实现难于解释清楚,那它是个差的想法。
|
||||
1. 如果一个实现很容易解释清楚,那它可能是个好的想法。
|
||||
@@ -71,7 +71,7 @@ PS: 核心复杂度的说明讨论可以参见[《代码大全》](http://book
|
||||
|
||||
**_[5]_** 这里的荷兰人指`Python`之父[_Guido_](https://zh.wikipedia.org/wiki/%E5%90%89%E5%A4%9A%C2%B7%E8%8C%83%E7%BD%97%E8%8B%8F%E5%A7%86),参见说明:[武汉大学开源技术俱乐部 技术交流 第1期](http://qianjigui.iteye.com/blog/266365)。
|
||||
|
||||
在这里作者[_TimPeters_](http://www.c2.com/cgi/wiki?TimPeters)即含蓄地表达了对`Python`之父[_Guido_](https://zh.wikipedia.org/wiki/%E5%90%89%E5%A4%9A%C2%B7%E8%8C%83%E7%BD%97%E8%8B%8F%E5%A7%86)的敬意,又体现了自己作为`Python`开发的傲娇,不是吗? 😁
|
||||
在这里作者[_TimPeters_](http://www.c2.com/cgi/wiki?TimPeters)即含蓄地表达了对`Python`之父[_Guido_](https://zh.wikipedia.org/wiki/%E5%90%89%E5%A4%9A%C2%B7%E8%8C%83%E7%BD%97%E8%8B%8F%E5%A7%86)的敬意,又体现了自己作为`Python`开发的傲娇,不是吗? 😁
|
||||
|
||||
**_[6] [7]_** 关于『Now/现在』、『never/决不』、『right now/马上』,个人理解,这个条目要说的是:
|
||||
|
||||
@@ -79,7 +79,7 @@ PS: 核心复杂度的说明讨论可以参见[《代码大全》](http://book
|
||||
|
||||
否则结果会是:
|
||||
|
||||
- 『马上』做 是 『世界上最不能相信』的话 😄 ,想想饭店服务员的话『您要的菜马上就好』,其实你自己知道后面往往就不会去做这个功能了。
|
||||
- 『马上』做 是 『世界上最不能相信』的话 😄 ,想想饭店服务员的话『您要的菜马上就好』,其实你自己知道后面往往就不会去做这个功能了。
|
||||
更多『世界上最不能相信』的话参见[世界上最不能相信的几句话](http://blog.renren.com/share/339618932/7590788371)。
|
||||
- 『马上』做 === 不经过思考的不做,结果系统没有做一个本该这个系统做的功能!然后这个功能在不合适的地方被实现,即系统设计有问题。
|
||||
|
||||
@@ -99,13 +99,13 @@ PS: 核心复杂度的说明讨论可以参见[《代码大全》](http://book
|
||||
|
||||
1. [Python(programming language) - Wikipedia](http://en.wikipedia.org/wiki/Python_%28programming_language%29#Programming_philosophy)
|
||||
1. [No programming language offers what Python does philosophically.](http://www.indicthreads.com/1062/no-programming-language-offers-what-python-does-philosophically/)
|
||||
在编程哲学上,`Python`超越了其它编程语言。
|
||||
在编程哲学上,`Python`超越了其它编程语言。
|
||||
1. [武汉大学开源技术俱乐部 技术交流 第1期](http://qianjigui.iteye.com/blog/266365)。
|
||||
这里还有其它有关`Python`有意思的东西。
|
||||
这里还有其它有关`Python`有意思的东西。
|
||||
1. 核心复杂度的说明参见[《代码大全》](http://book.douban.com/subject/1477390/)一书。
|
||||
1. [世界上最不能相信的几句话](http://blog.renren.com/share/339618932/7590788371)
|
||||
|
||||
# `Python` Philosophy原文
|
||||
# `Python` Philosophy原文
|
||||
|
||||
**The Zen of Python**, by Tim Peters
|
||||
|
||||
|
||||
Reference in New Issue
Block a user