diff --git a/README.md b/README.md index ccbb2ba171..970a67dab0 100644 --- a/README.md +++ b/README.md @@ -60,6 +60,7 @@ LCTT 的组成 * 2017/03/13 制作了 LCTT 主页、成员列表和成员主页,LCTT 主页将移动至 https://linux.cn/lctt 。 * 2017/03/16 提升 GHLandy、bestony、rusking 为新的 Core 成员。创建 Comic 小组。 * 2017/04/11 启用头衔制,为各位重要成员颁发头衔。 +* 2017/11/21 鉴于 qhwdw 快速而上佳的翻译质量,提升 qhwdw 为新的 Core 成员。 核心成员 ------------------------------- @@ -86,6 +87,7 @@ LCTT 的组成 - 核心成员 @Locez, - 核心成员 @ucasFL, - 核心成员 @rusking, +- 核心成员 @qhwdw, - 前任选题 @DeadFire, - 前任校对 @reinoir222, - 前任校对 @PurlingNayuki, diff --git a/published/20170202 Understanding Firewalld in Multi-Zone Configurations.md b/published/20170202 Understanding Firewalld in Multi-Zone Configurations.md new file mode 100644 index 0000000000..cabd0d6ad3 --- /dev/null +++ b/published/20170202 Understanding Firewalld in Multi-Zone Configurations.md @@ -0,0 +1,347 @@ +理解多区域配置中的 firewalld +============================================================ + +现在的新闻里充斥着服务器被攻击和数据失窃事件。对于一个阅读过安全公告博客的人来说,通过访问错误配置的服务器,利用最新暴露的安全漏洞或通过窃取的密码来获得系统控制权,并不是件多困难的事情。在一个典型的 Linux 服务器上的任何互联网服务都可能存在漏洞,允许未经授权的系统访问。 + +因为在应用程序层面上强化系统以防范任何可能的威胁是不可能做到的事情,而防火墙可以通过限制对系统的访问提供了安全保证。防火墙基于源 IP、目标端口和协议来过滤入站包。因为这种方式中,仅有几个 IP/端口/协议的组合与系统交互,而其它的方式做不到过滤。 + +Linux 防火墙是通过 netfilter 来处理的,它是内核级别的框架。这十几年来,iptables 被作为 netfilter 的用户态抽象层(LCTT 译注: userland,一个基本的 UNIX 系统是由 kernel 和 userland 两部分构成,除 kernel 以外的称为 userland)。iptables 将包通过一系列的规则进行检查,如果包与特定的 IP/端口/协议的组合匹配,规则就会被应用到这个包上,以决定包是被通过、拒绝或丢弃。 + +Firewalld 是最新的 netfilter 用户态抽象层。遗憾的是,由于缺乏描述多区域配置的文档,它强大而灵活的功能被低估了。这篇文章提供了一个示例去改变这种情况。 + +### Firewalld 的设计目标 + +firewalld 的设计者认识到大多数的 iptables 使用案例仅涉及到几个单播源 IP,仅让每个符合白名单的服务通过,而其它的会被拒绝。这种模式的好处是,firewalld 可以通过定义的源 IP 和/或网络接口将入站流量分类到不同区域zone。每个区域基于指定的准则按自己配置去通过或拒绝包。 + +另外的改进是基于 iptables 进行语法简化。firewalld 通过使用服务名而不是它的端口和协议去指定服务,使它更易于使用,例如,是使用 samba 而不是使用 UDP 端口 137 和 138 和 TCP 端口 139 和 445。它进一步简化语法,消除了 iptables 中对语句顺序的依赖。 + +最后,firewalld 允许交互式修改 netfilter,允许防火墙独立于存储在 XML 中的永久配置而进行改变。因此,下面的的临时修改将在下次重新加载时被覆盖: + +``` +# firewall-cmd +``` + +而,以下的改变在重加载后会永久保存: + +``` +# firewall-cmd --permanent +# firewall-cmd --reload +``` + +### 区域 + +在 firewalld 中最上层的组织是区域。如果一个包匹配区域相关联的网络接口或源 IP/掩码 ,它就是区域的一部分。可用的几个预定义区域: + +``` +# firewall-cmd --get-zones +block dmz drop external home internal public trusted work +``` + +任何配置了一个**网络接口**和/或一个**源**的区域就是一个活动区域active zone。列出活动的区域: + +``` +# firewall-cmd --get-active-zones +public + interfaces: eno1 eno2 +``` + +**Interfaces** (接口)是系统中的硬件和虚拟的网络适配器的名字,正如你在上面的示例中所看到的那样。所有的活动的接口都将被分配到区域,要么是默认的区域,要么是用户指定的一个区域。但是,一个接口不能被分配给多于一个的区域。 + +在缺省配置中,firewalld 设置所有接口为 public 区域,并且不对任何区域设置源。其结果是,`public` 区域是唯一的活动区域。 + +**Sources** (源)是入站 IP 地址的范围,它也可以被分配到区域。一个源(或重叠的源)不能被分配到多个区域。这样做的结果是产生一个未定义的行为,因为不清楚应该将哪些规则应用于该源。 + +因为指定一个源不是必需的,任何包都可以通过接口匹配而归属于一个区域,而不需要通过源匹配来归属一个区域。这表示通过使用优先级方式,优先到达多个指定的源区域,稍后将详细说明这种情况。首先,我们来检查 `public` 区域的配置: + +``` +# firewall-cmd --zone=public --list-all +public (default, active) + interfaces: eno1 eno2 + sources: + services: dhcpv6-client ssh + ports: + masquerade: no + forward-ports: + icmp-blocks: + rich rules: +# firewall-cmd --permanent --zone=public --get-target +default +``` + +逐行说明如下: + +* `public (default, active)` 表示 `public` 区域是默认区域(当接口启动时会自动默认),并且它是活动的,因为,它至少有一个接口或源分配给它。 +* `interfaces: eno1 eno2` 列出了这个区域上关联的接口。 +* `sources:` 列出了这个区域的源。现在这里什么都没有,但是,如果这里有内容,它们应该是这样的格式 xxx.xxx.xxx.xxx/xx。 +* `services: dhcpv6-client ssh` 列出了允许通过这个防火墙的服务。你可以通过运行 `firewall-cmd --get-services` 得到一个防火墙预定义服务的详细列表。 +* `ports:` 列出了一个允许通过这个防火墙的目标端口。它是用于你需要去允许一个没有在 firewalld 中定义的服务的情况下。 +* `masquerade: no` 表示这个区域是否允许 IP 伪装。如果允许,它将允许 IP 转发,它可以让你的计算机作为一个路由器。 +* `forward-ports:` 列出转发的端口。 +* `icmp-blocks:` 阻塞的 icmp 流量的黑名单。 +* `rich rules:` 在一个区域中优先处理的高级配置。 +* `default` 是目标区域,它决定了与该区域匹配而没有由上面设置中显式处理的包的动作。 + +### 一个简单的单区域配置示例 + +如果只是简单地锁定你的防火墙。简单地在删除公共区域上当前允许的服务,并重新加载: + +``` +# firewall-cmd --permanent --zone=public --remove-service=dhcpv6-client +# firewall-cmd --permanent --zone=public --remove-service=ssh +# firewall-cmd --reload +``` + +在下面的防火墙上这些命令的结果是: + +``` +# firewall-cmd --zone=public --list-all +public (default, active) + interfaces: eno1 eno2 + sources: + services: + ports: + masquerade: no + forward-ports: + icmp-blocks: + rich rules: +# firewall-cmd --permanent --zone=public --get-target +default +``` + +本着尽可能严格地保证安全的精神,如果发生需要在你的防火墙上临时开放一个服务的情况(假设是 ssh),你可以增加这个服务到当前会话中(省略 `--permanent`),并且指示防火墙在一个指定的时间之后恢复修改: + +``` +# firewall-cmd --zone=public --add-service=ssh --timeout=5m +``` + +这个 `timeout` 选项是一个以秒(`s`)、分(`m`)或小时(`h`)为单位的时间值。 + +### 目标 + +当一个区域处理它的源或接口上的一个包时,但是,没有处理该包的显式规则时,这时区域的目标target决定了该行为: + +* `ACCEPT`:通过这个包。 +* `%%REJECT%%`:拒绝这个包,并返回一个拒绝的回复。 +* `DROP`:丢弃这个包,不回复任何信息。 +* `default`:不做任何事情。该区域不再管它,把它踢到“楼上”。 + +在 firewalld 0.3.9 中有一个 bug (已经在 0.3.10 中修复),对于一个目标是除了“default”以外的源区域,不管允许的服务是什么,这的目标都会被应用。例如,一个使用目标 `DROP` 的源区域,将丢弃所有的包,甚至是白名单中的包。遗憾的是,这个版本的 firewalld 被打包到 RHEL7 和它的衍生版中,使它成为一个相当常见的 bug。本文中的示例避免了可能出现这种行为的情况。 + +### 优先权 + +活动区域中扮演两个不同的角色。关联接口行为的区域作为接口区域,并且,关联源行为的区域作为源区域(一个区域能够扮演两个角色)。firewalld 按下列顺序处理一个包: + +1. 相应的源区域。可以存在零个或一个这样的区域。如果这个包满足一个富规则rich rule、服务是白名单中的、或者目标没有定义,那么源区域处理这个包,并且在这里结束。否则,向上传递这个包。 +2. 相应的接口区域。肯定有一个这样的区域。如果接口处理这个包,那么到这里结束。否则,向上传递这个包。 +3. firewalld 默认动作。接受 icmp 包并拒绝其它的一切。 + +这里的关键信息是,源区域优先于接口区域。因此,对于多区域的 firewalld 配置的一般设计模式是,创建一个优先源区域来允许指定的 IP 对系统服务的提升访问,并在一个限制性接口区域限制其它访问。 + +### 一个简单的多区域示例 + +为演示优先权,让我们在 `public` 区域中将 `http` 替换成 `ssh`,并且为我们喜欢的 IP 地址,如 1.1.1.1,设置一个默认的 `internal` 区域。以下的命令完成这个任务: + +``` +# firewall-cmd --permanent --zone=public --remove-service=ssh +# firewall-cmd --permanent --zone=public --add-service=http +# firewall-cmd --permanent --zone=internal --add-source=1.1.1.1 +# firewall-cmd --reload +``` + +这些命令的结果是生成如下的配置: + +``` +# firewall-cmd --zone=public --list-all +public (default, active) + interfaces: eno1 eno2 + sources: + services: dhcpv6-client http + ports: + masquerade: no + forward-ports: + icmp-blocks: + rich rules: +# firewall-cmd --permanent --zone=public --get-target +default +# firewall-cmd --zone=internal --list-all +internal (active) + interfaces: + sources: 1.1.1.1 + services: dhcpv6-client mdns samba-client ssh + ports: + masquerade: no + forward-ports: + icmp-blocks: + rich rules: +# firewall-cmd --permanent --zone=internal --get-target +default +``` + +在上面的配置中,如果有人尝试从 1.1.1.1 去 `ssh`,这个请求将会成功,因为这个源区域(`internal`)被首先应用,并且它允许 `ssh` 访问。 + +如果有人尝试从其它的地址,如 2.2.2.2,去访问 `ssh`,它不是这个源区域的,因为和这个源区域不匹配。因此,这个请求被直接转到接口区域(`public`),它没有显式处理 `ssh`,因为,public 的目标是 `default`,这个请求被传递到默认动作,它将被拒绝。 + +如果 1.1.1.1 尝试进行 `http` 访问会怎样?源区域(`internal`)不允许它,但是,目标是 `default`,因此,请求将传递到接口区域(`public`),它被允许访问。 + +现在,让我们假设有人从 3.3.3.3 拖你的网站。要限制从那个 IP 的访问,简单地增加它到预定义的 `drop` 区域,正如其名,它将丢弃所有的连接: + +``` +# firewall-cmd --permanent --zone=drop --add-source=3.3.3.3 +# firewall-cmd --reload +``` + +下一次 3.3.3.3 尝试去访问你的网站,firewalld 将转发请求到源区域(`drop`)。因为目标是 `DROP`,请求将被拒绝,并且它不会被转发到接口区域(`public`)。 + +### 一个实用的多区域示例 + +假设你为你的组织的一台服务器配置防火墙。你希望允许全世界使用 `http` 和 `https` 的访问,你的组织(1.1.0.0/16)和工作组(1.1.1.0/8)使用 `ssh` 访问,并且你的工作组可以访问 `samba` 服务。使用 firewalld 中的区域,你可以用一个很直观的方式去实现这个配置。 + +`public` 这个命名,它的逻辑似乎是把全世界访问指定为公共区域,而 `internal` 区域用于为本地使用。从在 `public` 区域内设置使用 `http` 和 `https` 替换 `dhcpv6-client` 和 `ssh` 服务来开始: + +``` +# firewall-cmd --permanent --zone=public --remove-service=dhcpv6-client +# firewall-cmd --permanent --zone=public --remove-service=ssh +# firewall-cmd --permanent --zone=public --add-service=http +# firewall-cmd --permanent --zone=public --add-service=https +``` + +然后,取消 `internal` 区域的 `mdns`、`samba-client` 和 `dhcpv6-client` 服务(仅保留 `ssh`),并增加你的组织为源: + +``` +# firewall-cmd --permanent --zone=internal --remove-service=mdns +# firewall-cmd --permanent --zone=internal --remove-service=samba-client +# firewall-cmd --permanent --zone=internal --remove-service=dhcpv6-client +# firewall-cmd --permanent --zone=internal --add-source=1.1.0.0/16 +``` + +为容纳你提升的 `samba` 的权限,增加一个富规则: + +``` +# firewall-cmd --permanent --zone=internal --add-rich-rule='rule family=ipv4 source address="1.1.1.0/8" service name="samba" accept' +``` + +最后,重新加载,把这些变化拉取到会话中: + +``` +# firewall-cmd --reload +``` + +仅剩下少数的细节了。从一个 `internal` 区域以外的 IP 去尝试通过 `ssh` 到你的服务器,结果是回复一个拒绝的消息。它是 firewalld 默认的。更为安全的作法是去显示不活跃的 IP 行为并丢弃该连接。改变 `public` 区域的目标为 `DROP`,而不是 `default` 来实现它: + +``` +# firewall-cmd --permanent --zone=public --set-target=DROP +# firewall-cmd --reload +``` + +但是,等等,你不再可以 ping 了,甚至是从内部区域!并且 icmp (ping 使用的协议)并不在 firewalld 可以列入白名单的服务列表中。那是因为,icmp 是第 3 层的 IP 协议,它没有端口的概念,不像那些捆绑了端口的服务。在设置公共区域为 `DROP` 之前,ping 能够通过防火墙是因为你的 `default` 目标通过它到达防火墙的默认动作(default),即允许它通过。但现在它已经被删除了。 + +为恢复内部网络的 ping,使用一个富规则: + +``` +# firewall-cmd --permanent --zone=internal --add-rich-rule='rule protocol value="icmp" accept' +# firewall-cmd --reload +``` + +结果如下,这里是两个活动区域的配置: + +``` +# firewall-cmd --zone=public --list-all +public (default, active) + interfaces: eno1 eno2 + sources: + services: http https + ports: + masquerade: no + forward-ports: + icmp-blocks: + rich rules: +# firewall-cmd --permanent --zone=public --get-target +DROP +# firewall-cmd --zone=internal --list-all +internal (active) + interfaces: + sources: 1.1.0.0/16 + services: ssh + ports: + masquerade: no + forward-ports: + icmp-blocks: + rich rules: + rule family=ipv4 source address="1.1.1.0/8" service name="samba" accept + rule protocol value="icmp" accept +# firewall-cmd --permanent --zone=internal --get-target +default +``` + +这个设置演示了一个三层嵌套的防火墙。最外层,`public`,是一个接口区域,包含全世界的访问。紧接着的一层,`internal`,是一个源区域,包含你的组织,它是 `public` 的一个子集。最后,一个富规则增加到最内层,包含了你的工作组,它是 `internal` 的一个子集。 + +这里的关键信息是,当在一个场景中可以突破到嵌套层,最外层将使用接口区域,接下来的将使用一个源区域,并且在源区域中额外使用富规则。 + +### 调试 + +firewalld 采用直观范式来设计防火墙,但比它的前任 iptables 更容易产生歧义。如果产生无法预料的行为,或者为了更好地理解 firewalld 是怎么工作的,则可以使用 iptables 描述 netfilter 是如何配置操作的。前一个示例的输出如下,为了简单起见,将输出和日志进行了修剪: + +``` +# iptables -S +-P INPUT ACCEPT +... (forward and output lines) ... +-N INPUT_ZONES +-N INPUT_ZONES_SOURCE +-N INPUT_direct +-N IN_internal +-N IN_internal_allow +-N IN_internal_deny +-N IN_public +-N IN_public_allow +-N IN_public_deny +-A INPUT -m conntrack --ctstate RELATED,ESTABLISHED -j ACCEPT +-A INPUT -i lo -j ACCEPT +-A INPUT -j INPUT_ZONES_SOURCE +-A INPUT -j INPUT_ZONES +-A INPUT -p icmp -j ACCEPT +-A INPUT -m conntrack --ctstate INVALID -j DROP +-A INPUT -j REJECT --reject-with icmp-host-prohibited +... (forward and output lines) ... +-A INPUT_ZONES -i eno1 -j IN_public +-A INPUT_ZONES -i eno2 -j IN_public +-A INPUT_ZONES -j IN_public +-A INPUT_ZONES_SOURCE -s 1.1.0.0/16 -g IN_internal +-A IN_internal -j IN_internal_deny +-A IN_internal -j IN_internal_allow +-A IN_internal_allow -p tcp -m tcp --dport 22 -m conntrack --ctstate NEW -j ACCEPT +-A IN_internal_allow -s 1.1.1.0/8 -p udp -m udp --dport 137 -m conntrack --ctstate NEW -j ACCEPT +-A IN_internal_allow -s 1.1.1.0/8 -p udp -m udp --dport 138 -m conntrack --ctstate NEW -j ACCEPT +-A IN_internal_allow -s 1.1.1.0/8 -p tcp -m tcp --dport 139 -m conntrack --ctstate NEW -j ACCEPT +-A IN_internal_allow -s 1.1.1.0/8 -p tcp -m tcp --dport 445 -m conntrack --ctstate NEW -j ACCEPT +-A IN_internal_allow -p icmp -m conntrack --ctstate NEW -j ACCEPT +-A IN_public -j IN_public_deny +-A IN_public -j IN_public_allow +-A IN_public -j DROP +-A IN_public_allow -p tcp -m tcp --dport 80 -m conntrack --ctstate NEW -j ACCEPT +-A IN_public_allow -p tcp -m tcp --dport 443 -m conntrack --ctstate NEW -j ACCEPT +``` + +在上面的 iptables 输出中,新的链(以 `-N` 开始的行)是被首先声明的。剩下的规则是附加到(以 `-A` 开始的行) iptables 中的。已建立的连接和本地流量是允许通过的,并且入站包被转到 `INPUT_ZONES_SOURCE` 链,在那里如果存在相应的区域,IP 将被发送到那个区域。从那之后,流量被转到 `INPUT_ZONES` 链,从那里它被路由到一个接口区域。如果在那里它没有被处理,icmp 是允许通过的,无效的被丢弃,并且其余的都被拒绝。 + +### 结论 + +firewalld 是一个文档不足的防火墙配置工具,它的功能远比大多数人认识到的更为强大。以创新的区域范式,firewalld 允许系统管理员去分解流量到每个唯一处理它的分类中,简化了配置过程。因为它直观的设计和语法,它在实践中不但被用于简单的单一区域中也被用于复杂的多区域配置中。 + +-------------------------------------------------------------------------------- + +via: https://www.linuxjournal.com/content/understanding-firewalld-multi-zone-configurations?page=0,0 + +作者:[Nathan Vance][a] +译者:[qhwdw](https://github.com/qhwdw) +校对:[wxy](https://github.com/wxy) + +本文由 [LCTT](https://github.com/LCTT/TranslateProject) 原创编译,[Linux中国](https://linux.cn/) 荣誉推出 + +[a]:https://www.linuxjournal.com/users/nathan-vance +[1]:https://www.linuxjournal.com/tag/firewalls +[2]:https://www.linuxjournal.com/tag/howtos +[3]:https://www.linuxjournal.com/tag/networking +[4]:https://www.linuxjournal.com/tag/security +[5]:https://www.linuxjournal.com/tag/sysadmin +[6]:https://www.linuxjournal.com/users/william-f-polik +[7]:https://www.linuxjournal.com/users/nathan-vance diff --git a/sources/tech/20170227 Ubuntu Core in LXD containers.md b/published/20170227 Ubuntu Core in LXD containers.md similarity index 54% rename from sources/tech/20170227 Ubuntu Core in LXD containers.md rename to published/20170227 Ubuntu Core in LXD containers.md index 2206e85d8a..1f4b778b89 100644 --- a/sources/tech/20170227 Ubuntu Core in LXD containers.md +++ b/published/20170227 Ubuntu Core in LXD containers.md @@ -1,36 +1,28 @@ -Translating By LHRchina - - -Ubuntu Core in LXD containers +使用 LXD 容器运行 Ubuntu Core ============================================================ - -### Share or save - ![LXD logo](https://linuxcontainers.org/static/img/containers.png) -### What’s Ubuntu Core? +### Ubuntu Core 是什么? -Ubuntu Core is a version of Ubuntu that’s fully transactional and entirely based on snap packages. +Ubuntu Core 是完全基于 snap 包构建,并且完全事务化的 Ubuntu 版本。 -Most of the system is read-only. All installed applications come from snap packages and all updates are done using transactions. Meaning that should anything go wrong at any point during a package or system update, the system will be able to revert to the previous state and report the failure. +该系统大部分是只读的,所有已安装的应用全部来自 snap 包,完全使用事务化更新。这意味着不管在系统更新还是安装软件的时候遇到问题,整个系统都可以回退到之前的状态并且记录这个错误。 -The current release of Ubuntu Core is called series 16 and was released in November 2016. +最新版是在 2016 年 11 月发布的 Ubuntu Core 16。 -Note that on Ubuntu Core systems, only snap packages using confinement can be installed (no “classic” snaps) and that a good number of snaps will not fully work in this environment or will require some manual intervention (creating user and groups, …). Ubuntu Core gets improved on a weekly basis as new releases of snapd and the “core” snap are put out. +注意,Ubuntu Core 限制只能够安装 snap 包(而非 “传统” 软件包),并且有相当数量的 snap 包在当前环境下不能正常运行,或者需要人工干预(创建用户和用户组等)才能正常运行。随着新版的 snapd 和 “core” snap 包发布,Ubuntu Core 每周都会得到改进。 -### Requirements +### 环境需求 -As far as LXD is concerned, Ubuntu Core is just another Linux distribution. That being said, snapd does require unprivileged FUSE mounts and AppArmor namespacing and stacking, so you will need the following: +就 LXD 而言,Ubuntu Core 仅仅相当于另一个 Linux 发行版。也就是说,snapd 需要挂载无特权的 FUSE 和 AppArmor 命名空间以及软件栈,像下面这样: -* An up to date Ubuntu system using the official Ubuntu kernel +* 一个新版的使用 Ubuntu 官方内核的系统 +* 一个新版的 LXD -* An up to date version of LXD +### 创建一个 Ubuntu Core 容器 -### Creating an Ubuntu Core container - -The Ubuntu Core images are currently published on the community image server. -You can launch a new container with: +当前 Ubuntu Core 镜像发布在社区的镜像服务器。你可以像这样启动一个新的容器: ``` stgraber@dakara:~$ lxc launch images:ubuntu-core/16 ubuntu-core @@ -38,9 +30,9 @@ Creating ubuntu-core Starting ubuntu-core ``` -The container will take a few seconds to start, first executing a first stage loader that determines what read-only image to use and setup the writable layers. You don’t want to interrupt the container in that stage and “lxc exec” will likely just fail as pretty much nothing is available at that point. +这个容器启动需要一点点时间,它会先执行第一阶段的加载程序,加载程序会确定使用哪一个镜像(镜像是只读的),并且在系统上设置一个可读层,你不要在这一阶段中断容器执行,这个时候什么都没有,所以执行 `lxc exec` 将会出错。 -Seconds later, “lxc list” will show the container IP address, indicating that it’s booted into Ubuntu Core: +几秒钟之后,执行 `lxc list` 将会展示容器的 IP 地址,这表明已经启动了 Ubuntu Core: ``` stgraber@dakara:~$ lxc list @@ -51,7 +43,7 @@ stgraber@dakara:~$ lxc list +-------------+---------+----------------------+----------------------------------------------+------------+-----------+ ``` -You can then interact with that container the same way you would any other: +之后你就可以像使用其他的交互一样和这个容器进行交互: ``` stgraber@dakara:~$ lxc exec ubuntu-core bash @@ -63,11 +55,11 @@ pc-kernel 4.4.0-45-4 37 canonical - root@ubuntu-core:~# ``` -### Updating the container +### 更新容器 -If you’ve been tracking the development of Ubuntu Core, you’ll know that those versions above are pretty old. That’s because the disk images that are used as the source for the Ubuntu Core LXD images are only refreshed every few months. Ubuntu Core systems will automatically update once a day and then automatically reboot to boot onto the new version (and revert if this fails). +如果你一直关注着 Ubuntu Core 的开发,你应该知道上面的版本已经很老了。这是因为被用作 Ubuntu LXD 镜像的代码每隔几个月才会更新。Ubuntu Core 系统在重启时会检查更新并进行自动更新(更新失败会回退)。 -If you want to immediately force an update, you can do it with: +如果你想现在强制更新,你可以这样做: ``` stgraber@dakara:~$ lxc exec ubuntu-core bash @@ -81,7 +73,7 @@ series 16 root@ubuntu-core:~# ``` -And then reboot the system and check the snapd version again: +然后重启一下 Ubuntu Core 系统,然后看看 snapd 的版本。 ``` root@ubuntu-core:~# reboot @@ -95,7 +87,7 @@ series 16 root@ubuntu-core:~# ``` -You can get an history of all snapd interactions with +你也可以像下面这样查看所有 snapd 的历史记录: ``` stgraber@dakara:~$ lxc exec ubuntu-core snap changes @@ -105,9 +97,9 @@ ID Status Spawn Ready Summary 3 Done 2017-01-31T05:21:30Z 2017-01-31T05:22:45Z Refresh all snaps in the system ``` -### Installing some snaps +### 安装 Snap 软件包 -Let’s start with the simplest snaps of all, the good old Hello World: +以一个最简单的例子开始,经典的 Hello World: ``` stgraber@dakara:~$ lxc exec ubuntu-core bash @@ -117,7 +109,7 @@ root@ubuntu-core:~# hello-world Hello World! ``` -And then move on to something a bit more useful: +接下来让我们看一些更有用的: ``` stgraber@dakara:~$ lxc exec ubuntu-core bash @@ -125,9 +117,9 @@ root@ubuntu-core:~# snap install nextcloud nextcloud 11.0.1snap2 from 'nextcloud' installed ``` -Then hit your container over HTTP and you’ll get to your newly deployed Nextcloud instance. +之后通过 HTTP 访问你的容器就可以看到刚才部署的 Nextcloud 实例。 -If you feel like testing the latest LXD straight from git, you can do so with: +如果你想直接通过 git 测试最新版 LXD,你可以这样做: ``` stgraber@dakara:~$ lxc config set ubuntu-core security.nesting true @@ -156,7 +148,7 @@ What IPv6 address should be used (CIDR subnet notation, “auto” or “none” LXD has been successfully configured. ``` -And because container inception never gets old, lets run Ubuntu Core 16 inside Ubuntu Core 16: +已经设置过的容器不能回退版本,但是可以在 Ubuntu Core 16 中运行另一个 Ubuntu Core 16 容器: ``` root@ubuntu-core:~# lxc launch images:ubuntu-core/16 nested-core @@ -170,28 +162,29 @@ root@ubuntu-core:~# lxc list +-------------+---------+---------------------+-----------------------------------------------+------------+-----------+ ``` -### Conclusion +### 写在最后 -If you ever wanted to try Ubuntu Core, this is a great way to do it. It’s also a great tool for snap authors to make sure their snap is fully self-contained and will work in all environments. +如果你只是想试用一下 Ubuntu Core,这是一个不错的方法。对于 snap 包开发者来说,这也是一个不错的工具来测试你的 snap 包能否在不同的环境下正常运行。 -Ubuntu Core is a great fit for environments where you want to ensure that your system is always up to date and is entirely reproducible. This does come with a number of constraints that may or may not work for you. +如果你希望你的系统总是最新的,并且整体可复制,Ubuntu Core 是一个很不错的方案,不过这也会带来一些相应的限制,所以可能不太适合你。 -And lastly, a word of warning. Those images are considered as good enough for testing, but aren’t officially supported at this point. We are working towards getting fully supported Ubuntu Core LXD images on the official Ubuntu image server in the near future. +最后是一个警告,对于测试来说,这些镜像是足够的,但是当前并没有被正式的支持。在不久的将来,官方的 Ubuntu server 可以完整的支持 Ubuntu Core LXD 镜像。 -### Extra information +### 附录 -The main LXD website is at: [https://linuxcontainers.org/lxd][2] Development happens on Github at: [https://github.com/lxc/lxd][3] -Mailing-list support happens on: [https://lists.linuxcontainers.org][4] -IRC support happens in: #lxcontainers on irc.freenode.net -Try LXD online: [https://linuxcontainers.org/lxd/try-it][5] +- LXD 主站:[https://linuxcontainers.org/lxd][2] +- Github:[https://github.com/lxc/lxd][3] +- 邮件列表:[https://lists.linuxcontainers.org][4] +- IRC:#lxcontainers on irc.freenode.net +- 在线试用:[https://linuxcontainers.org/lxd/try-it][5] -------------------------------------------------------------------------------- via: https://insights.ubuntu.com/2017/02/27/ubuntu-core-in-lxd-containers/ -作者:[Stéphane Graber ][a] -译者:[译者ID](https://github.com/译者ID) -校对:[校对者ID](https://github.com/校对者ID) +作者:[Stéphane Graber][a] +译者:[aiwhj](https://github.com/aiwhj) +校对:[wxy](https://github.com/wxy) 本文由 [LCTT](https://github.com/LCTT/TranslateProject) 原创编译,[Linux中国](https://linux.cn/) 荣誉推出 diff --git a/published/20170608 The Life-Changing Magic of Tidying Up Code.md b/published/20170608 The Life-Changing Magic of Tidying Up Code.md new file mode 100644 index 0000000000..d9ef84a90a --- /dev/null +++ b/published/20170608 The Life-Changing Magic of Tidying Up Code.md @@ -0,0 +1,48 @@ +肯特·贝克:改变人生的代码整理魔法 +========== + +> 本文作者肯特·贝克Kent Beck,是最早研究软件开发的模式和重构的人之一,是敏捷开发的开创者之一,更是极限编程和测试驱动开发的创始人,同时还是 Smalltalk 和 JUnit 的作者,对当今世界的软件开发影响深远。现在 Facebook 工作。 + +本周我一直在整理 Facebook 代码,而且我喜欢这个工作。我的职业生涯中已经整理了数千小时的代码,我有一套使这种整理更加安全、有趣和高效的规则。 + +整理工作是通过一系列短小而安全的步骤进行的。事实上,规则一就是**如果这很难,那就不要去做**。我以前在晚上做填字游戏。如果我卡住那就去睡觉,第二天晚上那些没有发现的线索往往很容易发现。与其想要一心搞个大的,不如在遇到阻力的时候停下来。 + +整理会陷入这样一种感觉:你错失的要比你从一个个成功中获得的更多(稍后会细说)。第二条规则是**当你充满活力时开始,当你累了时停下来**。起来走走。如果还没有恢复精神,那这一天的工作就算做完了。 + +只有在仔细追踪其它变化的时候(我把它和最新的差异搞混了),整理工作才可以与开发同步进行。第三条规则是**立即完成每个环节的工作**。与功能开发所不同的是,功能开发只有在完成一大块工作时才有意义,而整理是基于时间一点点完成的。 + +整理在任何步骤中都只需要付出不多的努力,所以我会在任何步骤遇到麻烦的时候放弃。所以,规则四是**两次失败后恢复**。如果我整理代码,运行测试,并遇到测试失败,那么我会立即修复它。如果我修复失败,我会立即恢复到上次已知最好的状态。 + +即便没有闪亮的新设计的愿景,整理也是有用的。不过,有时候我想看看事情会如何发展,所以第五条就是**实践**。执行一系列的整理和还原。第二次将更快,你会更加熟悉避免哪些坑。 + +只有在附带损害的风险较低,审查整理变化的成本也较低的时候整理才有用。规则六是**隔离整理**。如果你错过了在编写代码中途整理的机会,那么接下来可能很困难。要么完成并接着整理,要么还原、整理并进行修改。 + +试试这些。将临时申明的变量移动到它第一次使用的位置,简化布尔表达式(`return expression == True`?),提取一个 helper,将逻辑或状态的范围缩小到实际使用的位置。 + +### 规则 + +- 规则一、 如果这很难,那就不要去做 +- 规则二、 当你充满活力时开始,当你累了时停下来 +- 规则三、 立即完成每个环节工作 +- 规则四、 两次失败后恢复 +- 规则五、 实践 +- 规则六、 隔离整理 + +### 尾声 + +我通过严格地整理改变了架构、提取了框架。这种方式可以安全地做出重大改变。我认为这是因为,虽然每次整理的成本是不变的,但回报是指数级的,但我需要数据和模型来解释这个假说。 + +-------------------------------------------------------------------------------- + +via: https://www.facebook.com/notes/kent-beck/the-life-changing-magic-of-tidying-up-code/1544047022294823/ + +作者:[KENT BECK][a] +译者:[geekpi](https://github.com/geekpi) +校对:[wxy](https://github.com/wxy) + +本文由 [LCTT](https://github.com/LCTT/TranslateProject) 原创编译,[Linux中国](https://linux.cn/) 荣誉推出 + +[a]:https://www.facebook.com/kentlbeck +[1]:https://www.facebook.com/notes/kent-beck/the-life-changing-magic-of-tidying-up-code/1544047022294823/?utm_source=wanqu.co&utm_campaign=Wanqu+Daily&utm_medium=website# +[2]:https://www.facebook.com/kentlbeck +[3]:https://www.facebook.com/notes/kent-beck/the-life-changing-magic-of-tidying-up-code/1544047022294823/ diff --git a/published/20170706 Wildcard Certificates Coming January 2018.md b/published/20170706 Wildcard Certificates Coming January 2018.md new file mode 100644 index 0000000000..9095f72341 --- /dev/null +++ b/published/20170706 Wildcard Certificates Coming January 2018.md @@ -0,0 +1,33 @@ +Let’s Encrypt :2018 年 1 月发布通配证书 +============================================================ + +Let’s Encrypt 将于 2018 年 1 月开始发放通配证书。通配证书是一个经常需要的功能,并且我们知道在一些情况下它可以使 HTTPS 部署更简单。我们希望提供通配证书有助于加速网络向 100% HTTPS 进展。 + +Let’s Encrypt 目前通过我们的全自动 DV 证书颁发和管理 API 保护了 4700 万个域名。自从 Let's Encrypt 的服务于 2015 年 12 月发布以来,它已经将加密网页的数量从 40% 大大地提高到了 58%。如果你对通配证书的可用性以及我们达成 100% 的加密网页的使命感兴趣,我们请求你为我们的[夏季筹款活动][1](LCTT 译注:之前的夏季活动,原文发布于今年夏季)做出贡献。 + +通配符证书可以保护基本域的任何数量的子域名(例如 *.example.com)。这使得管理员可以为一个域及其所有子域使用单个证书和密钥对,这可以使 HTTPS 部署更加容易。 + +通配符证书将通过我们[即将发布的 ACME v2 API 终端][2]免费提供。我们最初只支持通过 DNS 进行通配符证书的基础域验证,但是随着时间的推移可能会探索更多的验证方式。我们鼓励人们在我们的[社区论坛][3]上提出任何关于通配证书支持的问题。 + +我们决定在夏季筹款活动中宣布这一令人兴奋的进展,因为我们是一个非营利组织,这要感谢使用我们服务的社区的慷慨支持。如果你想支持一个更安全和保密的网络,[现在捐赠吧][4]! + +我们要感谢我们的[社区][5]和我们的[赞助者][6],使我们所做的一切成为可能。如果你的公司或组织能够赞助 Let's Encrypt,请发送电子邮件至 [sponsor@letsencrypt.org][7]。 + +-------------------------------------------------------------------------------- + +via: https://letsencrypt.org/2017/07/06/wildcard-certificates-coming-jan-2018.html + +作者:[Josh Aas][a] +译者:[geekpi](https://github.com/geekpi) +校对:[wxy](https://github.com/wxy) + +本文由 [LCTT](https://github.com/LCTT/TranslateProject) 原创编译,[Linux中国](https://linux.cn/) 荣誉推出 + +[a]:https://letsencrypt.org/2017/07/06/wildcard-certificates-coming-jan-2018.html +[1]:https://letsencrypt.org/donate/ +[2]:https://letsencrypt.org/2017/06/14/acme-v2-api.html +[3]:https://community.letsencrypt.org/ +[4]:https://letsencrypt.org/donate/ +[5]:https://letsencrypt.org/getinvolved/ +[6]:https://letsencrypt.org/sponsors/ +[7]:mailto:sponsor@letsencrypt.org diff --git a/published/20170825 Guide to Linux App Is a Handy Tool for Every Level of Linux User.md b/published/20170825 Guide to Linux App Is a Handy Tool for Every Level of Linux User.md new file mode 100644 index 0000000000..ac968d7b8c --- /dev/null +++ b/published/20170825 Guide to Linux App Is a Handy Tool for Every Level of Linux User.md @@ -0,0 +1,149 @@ +Linux 用户的手边工具:Guide to Linux +============================================================ + +![Guide to Linux](https://www.linux.com/sites/lcom/files/styles/rendered_file/public/guide-to-linux.png?itok=AAcrxjjc "Guide to Linux") + +> “Guide to Linux” 这个应用并不完美,但它是一个非常好的工具,可以帮助你学习 Linux 命令。 + +还记得你初次使用 Linux 时的情景吗?对于有些人来说,他的学习曲线可能有些挑战性。比如,在 `/usr/bin` 中能找到许多命令。在我目前使用的 Elementary OS 系统中,命令的数量是 1944 个。当然,这并不全是真实的命令(或者,我会使用到的命令数量),但这个数目是很多的。 + +正因为如此(并且不同平台不一样),现在,新用户(和一些已经熟悉的用户)需要一些帮助。 + +对于每个管理员来说,这些技能是必须具备的: + +* 熟悉平台 +* 理解命令 +* 编写 Shell 脚本 + +当你寻求帮助时,有时,你需要去“阅读那些该死的手册”(Read the Fine/Freaking/Funky Manual,LCTT 译注:一个网络用语,简写为 RTFM),但是当你自己都不知道要找什么的时候,它就没办法帮到你了。在那个时候,你就会为你拥有像 [Guide to Linux][15] 这样的手机应用而感到高兴。 + +不像你在 Linux.com 上看到的那些大多数的内容,这篇文章只是介绍一个 Android 应用的。为什么呢?因为这个特殊的 应用是用来帮助用户学习 Linux 的。 + +而且,它做的很好。 + +关于这个应用我清楚地告诉你 —— 它并不完美。Guide to Linux 里面充斥着很烂的英文,糟糕的标点符号,并且(如果你是一个纯粹主义者),它从来没有提到过 GNU。在这之上,它有一个特别的功能(通常它对用户非常有用)功能不是很有用(LCTT 译注:是指终端模拟器,后面会详细解释)。除此之外,我敢说 Guide to Linux 可能是 Linux 平台上最好的一个移动端的 “口袋指南”。 + +对于这个应用,你可能会喜欢它的如下特性: + +* 离线使用 +* Linux 教程 +* 基础的和高级的 Linux 命令的详细介绍 +* 包含了命令示例和语法 +* 专用的 Shell 脚本模块 + +除此以外,Guide to Linux 是免费提供的(尽管里面有一些广告)。如果你想去除广告,它有一个应用内的购买,($2.99 USD/年)可以去消除广告。 + +让我们来安装这个应用,来看一看它的构成。 + +### 安装 + +像所有的 Android 应用一样,安装 Guide to Linux 是非常简单的。按照以下简单的几步就可以安装它了: + +1. 打开你的 Android 设备上的 Google Play 商店 +2. 搜索 Guide to Linux +3. 找到 Essence Infotech 的那个,并轻触进入 +4. 轻触 Install +5. 允许安装 + +安装完成后,你可以在你的应用抽屉App Drawer或主屏幕上(或者两者都有)上找到它去启动 Guide to Linux 。轻触图标去启动这个应用。 + +### 使用 + +让我们看一下 Guide to Linux 的每个功能。我发现某些功能比其它的更有帮助,或许你的体验会不一样。在我们分别讲解之前,我将重点提到其界面。开发者在为这个应用创建一个易于使用的界面方面做的很好。 + +从主窗口中(图 1),你可以获取四个易于访问的功能。 + +![Guide to Linux main window](https://www.linux.com/sites/lcom/files/styles/floated_images/public/guidetolinux1.jpg?itok=UJhPP80J "Guide to Linux main window") + +*图 1: The Guide to Linux 主窗口。[已获授权][1]* + +轻触四个图标中的任何一个去启动一个功能,然后,准备去学习。 + +### 教程 + +让我们从这个应用教程的最 “新手友好” 的功能开始。打开“Tutorial”功能,然后,将看到该教程的欢迎部分,“Linux 操作系统介绍”(图 2)。 + +![The Tutorial](https://www.linux.com/sites/lcom/files/styles/floated_images/public/guidetolinux2.jpg?itok=LiJ8pHdS "The Tutorial") + +*图 2:教程开始。[已获授权][2]* + +如果你轻触 “汉堡包菜单” (左上角的三个横线),显示了内容列表(图 3),因此,你可以在教程中选择任何一个可用部分。 + +![Tutorial TOC](https://www.linux.com/sites/lcom/files/styles/floated_images/public/guidetolinux3_0.jpg?itok=5nJNeYN- "Tutorial TOC") + +*图 3:教程的内容列表。[已获授权][3]* + +如果你现在还没有注意到,Guide to Linux 教程部分是每个主题的一系列短文的集合。短文包含图片和链接(有时候),链接将带你到指定的 web 网站(根据主题的需要)。这里没有交互,仅仅只能阅读。但是,这是一个很好的起点,由于开发者在描述各个部分方面做的很好(虽然有语法问题)。 + +尽管你可以在窗口的顶部看到一个搜索选项,但是,我还是没有发现这一功能的任何效果 —— 但是,你可以试一下。 + +对于 Linux 新手来说,如果希望获得 Linux 管理的技能,你需要去阅读整个教程。完成之后,转到下一个主题。 + +### 命令 + +命令功能类似于手机上的 man 页面一样,是大量的频繁使用的 Linux 命令。当你首次打开它,欢迎页面将详细解释使用命令的益处。 + +读完之后,你可以轻触向右的箭头(在屏幕底部)或轻触 “汉堡包菜单” ,然后从侧边栏中选择你想去学习的其它命令。(图 4) + +![Commands](https://www.linux.com/sites/lcom/files/styles/floated_images/public/guidetolinux4.jpg?itok=Rmzfb8Or "Commands") + +*图 4:命令侧边栏允许你去查看列出的命令。[已获授权][4]* + +轻触任意一个命令,你可以阅读这个命令的解释。每个命令解释页面和它的选项都提供了怎么去使用的示例。 + +### Shell 脚本 + +在这个时候,你开始熟悉 Linux 了,并对命令已经有一定程序的掌握。现在,是时候去熟悉 shell 脚本了。这个部分的设置方式与教程部分和命令部分相同。 + +你可以打开内容列表的侧边栏,然后打开包含 shell 脚本教程的任意部分(图 5)。 + +![Shell Script](https://www.linux.com/sites/lcom/files/styles/floated_images/public/guidetolinux-5-new.jpg?itok=EDlZ92IA "Shell Script") + +*图 5:Shell 脚本节看上去很熟悉。[已获授权][5]* + +开发者在解释如何最大限度地利用 shell 脚本方面做的很好。对于任何有兴趣学习 shell 脚本细节的人来说,这是个很好的起点。 + +### 终端 + +现在我们到了一个新的地方,开发者在这个应用中包含了一个终端模拟器。遗憾的是,当你在一个没有 “root” 权限的 Android 设备上安装这个应用时,你会发现你被限制在一个只读文件系统中,在那里,大部分命令根本无法工作。但是,我在一台 Pixel 2 (通过 Android 应用商店)安装的 Guide to Linux 中,可以使用更多的这个功能(还只是较少的一部分)。在一台 OnePlus 3 (非 root 过的)上,不管我改变到哪个目录,我都是得到相同的错误信息 “permission denied”,甚至是一个简单的命令也如此。 + +在 Chromebook 上,不管怎么操作,它都是正常的(图 6)。可以说,它可以一直很好地工作在一个只读操作系统中(因此,你不能用它进行真正的工作或创建新文件)。 + +![Permission denied](https://www.linux.com/sites/lcom/files/styles/rendered_file/public/guidetolinux6_0.jpg?itok=cVENH5lM "Permission denied") + +*图 6: 可以完美地(可以这么说)用一个终端模拟器去工作。[已获授权][6]* + +记住,这并不是真实的成熟终端,但却是一个新用户去熟悉终端是怎么工作的一种方法。遗憾的是,大多数用户只会发现自己对这个工具的终端功能感到沮丧,仅仅是因为,它们不能使用他们在其它部分学到的东西。开发者可能将这个终端功能打造成了一个 Linux 文件系统沙箱,因此,用户可以真实地使用它去学习。每次用户打开那个工具,它将恢复到原始状态。这只是我一个想法。 + +### 写在最后… + +尽管终端功能被一个只读文件系统所限制(几乎到了没法使用的程序),Guide to Linux 仍然是一个新手学习 Linux 的好工具。在 guide to Linux 中,你将学习关于 Linux、命令、和 shell 脚本的很多知识,以便在你安装你的第一个发行版之前,让你学习 Linux 有一个好的起点。 + +-------------------------------------------------------------------------------- + +via: https://www.linux.com/learn/intro-to-linux/2017/8/guide-linux-app-handy-tool-every-level-linux-user + +作者:[JACK WALLEN][a] +译者:[qhwdw](https://github.com/qhwdw) +校对:[wxy](https://github.com/wxy) + +本文由 [LCTT](https://github.com/LCTT/TranslateProject) 原创编译,[Linux中国](https://linux.cn/) 荣誉推出 + +[a]:https://www.linux.com/users/jlwallen +[1]:https://www.linux.com/licenses/category/used-permission +[2]:https://www.linux.com/licenses/category/used-permission +[3]:https://www.linux.com/licenses/category/used-permission +[4]:https://www.linux.com/licenses/category/used-permission +[5]:https://www.linux.com/licenses/category/used-permission +[6]:https://www.linux.com/licenses/category/used-permission +[7]:https://www.linux.com/licenses/category/used-permission +[8]:https://www.linux.com/files/images/guidetolinux1jpg +[9]:https://www.linux.com/files/images/guidetolinux2jpg +[10]:https://www.linux.com/files/images/guidetolinux3jpg-0 +[11]:https://www.linux.com/files/images/guidetolinux4jpg +[12]:https://www.linux.com/files/images/guidetolinux-5-newjpg +[13]:https://www.linux.com/files/images/guidetolinux6jpg-0 +[14]:https://www.linux.com/files/images/guide-linuxpng +[15]:https://play.google.com/store/apps/details?id=com.essence.linuxcommands +[16]:https://training.linuxfoundation.org/linux-courses/system-administration-training/introduction-to-linux +[17]:https://www.addtoany.com/share#url=https%3A%2F%2Fwww.linux.com%2Flearn%2Fintro-to-linux%2F2017%2F8%2Fguide-linux-app-handy-tool-every-level-linux-user&title=Guide%20to%20Linux%20App%20Is%20a%20Handy%20Tool%20for%20Every%20Level%20of%20Linux%20User diff --git a/published/20170905 GIVE AWAY YOUR CODE BUT NEVER YOUR TIME.md b/published/20170905 GIVE AWAY YOUR CODE BUT NEVER YOUR TIME.md new file mode 100644 index 0000000000..c6397c098e --- /dev/null +++ b/published/20170905 GIVE AWAY YOUR CODE BUT NEVER YOUR TIME.md @@ -0,0 +1,85 @@ +放弃你的代码,而不是你的时间 +============================================================ + +作为软件开发人员,我认为我们可以认同开源代码^注1 已经[改变了世界][9]。它的公共性质去除了壁垒,可以让软件可以变的最好。但问题是,太多有价值的项目由于领导者的精力耗尽而停滞不前: + +>“我没有时间和精力去投入开源了。我在开源上没有得到任何收入,所以我在那上面花的时间,我可以用在‘生活上的事’,或者写作上……正因为如此,我决定现在结束我所有的开源工作。” +> +>—[Ryan Bigg,几个 Ruby 和 Elixir 项目的前任维护者][1] +> +>“这也是一个巨大的机会成本,由于我无法同时学习或者完成很多事情,FubuMVC 占用了我很多的时间,这是它现在必须停下来的主要原因。” +> +>—[前 FubuMVC 项目负责人 Jeremy Miller][2] +> +>“当我们决定要孩子的时候,我可能会放弃开源,我预计最终解决我问题的方案将是:核武器。” +> +>—[Nolan Lawson,PouchDB 的维护者之一][3] + +我们需要的是一种新的行业规范,即项目领导者将_总是_能获得(其付出的)时间上的补偿。我们还需要抛弃的想法是, 任何提交问题或合并请求的开发人员都自动会得到维护者的注意。 + +我们先来回顾一下开源代码在市场上的作用。它是一个积木。它是[实用软件][10],是企业为了在别处获利而必须承担的成本。如果用户能够理解该代码的用途并且发现它比替代方案(闭源专用、定制的内部解决方案等)更有价值,那么围绕该软件的社区就会不断增长。它可以更好,更便宜,或两者兼而有之。 + +如果一个组织需要改进该代码,他们可以自由地聘请任何他们想要的开发人员。通常情况下[为了他们的利益][11]会将改进贡献给社区,因为由于代码合并的复杂性,这是他们能够轻松地从其他用户获得未来改进的唯一方式。这种“引力”倾向于把社区聚集在一起。 + +但是它也会加重项目维护者的负担,因为他们必须对这些改进做出反应。他们得到了什么回报?最好的情况是,这些社区贡献可能是他们将来可以使用的东西,但现在不是。最坏的情况下,这只不过是一个带着利他主义面具的自私请求罢了。 + +有一类开源项目避免了这个陷阱。Linux、MySQL、Android、Chromium 和 .NET Core 除了有名,有什么共同点么?他们都对一个或多个大型企业具有_战略性重要意义_,因为它们满足了这些利益。[聪明的公司商品化他们的商品][12],没有什么比开源软件便宜的商品了。红帽需要那些使用 Linux 的公司来销售企业级 Linux,Oracle 使用 MySQL 作为销售 MySQL Enterprise 的引子,谷歌希望世界上每个人都拥有电话和浏览器,而微软则试图将开发者锁定在平台上然后将它们拉入 Azure 云。这些项目全部由各自公司直接资助。 + +但是那些其他的项目呢,那些不是大玩家核心战略的项目呢? + +如果你是其中一个项目的负责人,请向社区成员收取年费。_开放的源码,封闭的社区_。给用户的信息应该是“尽你所愿地使用代码,但如果你想影响项目的未来,请_为我们的时间支付_。”将非付费用户锁定在论坛和问题跟踪之外,并忽略他们的电子邮件。不支付的人应该觉得他们错过了派对。 + +还要向贡献者收取合并非普通的合并请求的时间花费。如果一个特定的提交不会立即给你带来好处,请为你的时间收取全价。要有原则并[记住 YAGNI][13]。 + +这会导致一个极小的社区和更多的分支么?绝对。但是,如果你坚持不懈地构建自己的愿景,并为其他人创造价值,他们会尽快为要做的贡献而支付。_合并贡献的意愿是[稀缺资源][4]_。如果没有它,用户必须反复地将它们的变化与你发布的每个新版本进行协调。 + +如果你想在代码库中保持高水平的[概念完整性][14],那么限制社区是特别重要的。有[自由贡献政策][15]的无领导者项目没有必要收费。 + +为了实现更大的愿景,而不是单独为自己的业务支付成本,而是可能使其他人受益,去[众筹][16]吧。有许多成功的故事: + +- [Font Awesome 5][5] +- [Ruby enVironment Management (RVM)][6] +- [Django REST framework 3][7] + +[众筹有局限性][17]。它[不适合][18][大型项目][19]。但是,开源代码也是实用软件,它不需要雄心勃勃、冒险的破局者。它已经一点点地[渗透到每个行业][20]。 + +这些观点代表着一条可持续发展的道路,也可以解决[开源的多样性问题][21],这可能源于其历史上无偿的性质。但最重要的是,我们要记住,[我们一生中只留下那么多的按键次数][22],而且我们总有一天会后悔那些我们浪费的东西。 + +- 注 1 :当我说“开源”时,我的意思是代码[许可][8]以某种方式来构建专有的东西。这通常意味着一个宽松许可证(MIT 或 Apache 或 BSD),但并非总是如此。Linux 是当今科技行业的核心,但是是以 GPL 授权的。_ + +感谢 Jason Haley、Don McNamara、Bryan Hogan 和 Nadia Eghbal 阅读了这篇文章的草稿。 + +-------------------------------------------------------------------------------- + +via: http://wgross.net/essays/give-away-your-code-but-never-your-time + +作者:[William Gross][a] +译者:[geekpi](https://github.com/geekpi) +校对:[wxy](https://github.com/wxy) + +本文由 [LCTT](https://github.com/LCTT/TranslateProject) 原创编译,[Linux中国](https://linux.cn/) 荣誉推出 + +[a]:http://wgross.net/#about-section +[1]:http://ryanbigg.com/2015/11/open-source-work +[2]:https://jeremydmiller.com/2014/04/03/im-throwing-in-the-towel-in-fubumvc/ +[3]:https://nolanlawson.com/2017/03/05/what-it-feels-like-to-be-an-open-source-maintainer/ +[4]:https://hbr.org/2010/11/column-to-win-create-whats-scarce +[5]:https://www.kickstarter.com/projects/232193852/font-awesome-5 +[6]:https://www.bountysource.com/teams/rvm/fundraiser +[7]:https://www.kickstarter.com/projects/tomchristie/django-rest-framework-3 +[8]:https://choosealicense.com/ +[9]:https://www.wired.com/insights/2013/07/in-a-world-without-open-source/ +[10]:https://martinfowler.com/bliki/UtilityVsStrategicDichotomy.html +[11]:https://tessel.io/blog/67472869771/monetizing-open-source +[12]:https://www.joelonsoftware.com/2002/06/12/strategy-letter-v/ +[13]:https://martinfowler.com/bliki/Yagni.html +[14]:http://wiki.c2.com/?ConceptualIntegrity +[15]:https://opensource.com/life/16/5/growing-contributor-base-modern-open-source +[16]:https://poststatus.com/kickstarter-open-source-project/ +[17]:http://blog.felixbreuer.net/2013/04/24/crowdfunding-for-open-source.html +[18]:https://www.indiegogo.com/projects/geary-a-beautiful-modern-open-source-email-client#/ +[19]:http://www.itworld.com/article/2708360/open-source-tools/canonical-misses-smartphone-crowdfunding-goal-by--19-million.html +[20]:http://www.infoworld.com/article/2914643/open-source-software/rise-and-rise-of-open-source.html +[21]:http://readwrite.com/2013/12/11/open-source-diversity/ +[22]:http://keysleft.com/ +[23]:http://wgross.net/essays/give-away-your-code-but-never-your-time diff --git a/published/20170928 3 Python web scrapers and crawlers.md b/published/20170928 3 Python web scrapers and crawlers.md new file mode 100644 index 0000000000..da15a8c58f --- /dev/null +++ b/published/20170928 3 Python web scrapers and crawlers.md @@ -0,0 +1,98 @@ +三种 Python 网络内容抓取工具与爬虫 +============================================================ + +> 运用这些很棒的 Python 爬虫工具来获取你需要的数据。 + +![ python网络内容抓取工具与爬虫](https://opensource.com/sites/default/files/styles/image-full-size/public/lead-images/openweb-osdc-lead.png?itok=yjU4KliG "Python web scrapers and crawlers") + +在一个理想的世界里,你需要的所有数据都将以公开而文档完备的格式清晰地展现,你可以轻松地下载并在任何你需要的地方使用。 + +然而,在真实世界里,数据是凌乱的,极少被打包成你需要的样子,要么经常是过期的。 + +你所需要的信息经常是潜藏在一个网站里。相比一些清晰地、有调理地呈现数据的网站,更多的网站则不是这样的。[爬取数据][33]crawling[挖掘数据][34]scraping、加工数据、整理数据这些是获取整个网站结构来绘制网站拓扑来收集数据所必须的活动,这些可以是以网站的格式储存的或者是储存在一个专有数据库中。 + +也许在不久的将来,你需要通过爬取和挖掘来获得一些你需要的数据,当然你几乎肯定需要进行一点点的编程来正确的获取。你要怎么做取决于你自己,但是我发现 Python 社区是一个很好的提供者,它提供了工具、框架以及文档来帮助你从网站上获取数据。 + +在我们进行之前,这里有一个小小的请求:在你做事情之前请思考,以及请耐心。抓取这件事情并不简单。不要把网站爬下来只是复制一遍,并其它人的工作当成是你自己的东西(当然,没有许可)。要注意版权和许可,以及你所爬行的内容应用哪一个标准。尊重 [robots.txt][15] 文件。不要频繁的针对一个网站,这将导致真实的访问者会遇到访问困难的问题。 + +在知晓这些警告之后,这里有一些很棒的 Python 网站爬虫工具,你可以用来获得你需要的数据。 + +### Pyspider + +让我们先从 [pyspider][16] 开始介绍。这是一个带有 web 界面的网络爬虫,让与使之容易跟踪多个爬虫。其具有扩展性,支持多个后端数据库和消息队列。它还具有一些方便的特性,从优先级到再次访问抓取失败的页面,此外还有通过时间顺序来爬取和其他的一些特性。Pyspider 同时支持 Python 2 和 Python 3。为了实现一个更快的爬取,你可以在分布式的环境下一次使用多个爬虫进行爬取。 + +Pyspyder 的基本用法都有良好的 [文档说明][17] ,包括简单的代码片段。你能通过查看一个 [在线的样例][18] 来体验用户界面。它在 Apache 2 许可证下开源,Pyspyder 仍然在 GitHub 上积极地开发。 + +### MechanicalSoup + +[MechanicalSoup][19] 是一个基于极其流行而异常多能的 HTML 解析库 [Beautiful Soup][20] 建立的爬虫库。如果你的爬虫需要相当的简单,但是又要求检查一些选择框或者输入一些文字,而你又不想为这个任务单独写一个爬虫,那么这会是一个值得考虑的选择。 + +MechanicalSoup 在 MIT 许可证下开源。查看 GitHub 上该项目的 [example.py][21] 样例文件来获得更多的用法。不幸的是,到目前为止,这个项目还没有一个很好的文档。 + +### Scrapy + +[Scrapy][22] 是一个有着活跃社区支持的抓取框架,在那里你可以建造自己的抓取工具。除了爬取和解析工具,它还能将它收集的数据以 JSON 或者 CSV 之类的格式轻松输出,并存储在一个你选择的后端数据库。它还有许多内置的任务扩展,例如 cookie 处理、代理欺骗、限制爬取深度等等,同时还可以建立你自己附加的 API。 + +要了解 Scrapy,你可以查看[网上的文档][23]或者是访问它诸多的[社区][24]资源,包括一个 IRC 频道、Reddit 子版块以及关注他们的 StackOverflow 标签。Scrapy 的代码在 3 句版 BSD 许可证下开源,你可以在 [GitHub][25] 上找到它们。 + +如果你完全不熟悉编程,[Portia][26] 提供了一个易用的可视化的界面。[scrapinghub.com][27] 则提供一个托管的版本。 + +### 其它 + +* [Cola][6] 自称它是个“高级的分布式爬取框架”,如果你在寻找一个 Python 2 的方案,这也许会符合你的需要,但是注意它已经有超过两年没有更新了。 +* [Demiurge][7] 是另一个可以考虑的潜在候选者,它同时支持 Python 2和 Python 3,虽然这个项目的发展较为缓慢。 +* 如果你要解析一些 RSS 和 Atom 数据,[Feedparser][8] 或许是一个有用的项目。 +* [Lassie][9] 让从网站检索像说明、标题、关键词或者是图片一类的基本内容变得简单。 +* [RoboBrowser][10] 是另一个简单的库,它基于 Python 2 或者 Python 3,它具有按钮点击和表格填充的基本功能。虽然它有一段时间没有更新了,但是它仍然是一个不错的选择。 + +* * * + +这远不是一个完整的列表,当然,如果你是一个编程专家,你可以选择采取你自己的方法而不是使用这些框架中的一个。或者你发现一个用其他语言编写的替代品。例如 Python 编程者可能更喜欢 [Python 附带的][28] [Selenium][29],它可以在不使用实际浏览器的情况下进行爬取。如果你有喜欢的爬取和挖掘工具,请在下面评论让我们知道。 + +(题图:[You as a Machine][13]. Modified by Rikki Endsley. [CC BY-SA 2.0][14]) + +-------------------------------------------------------------------------------- + +via: https://opensource.com/resources/python/web-scraper-crawler + +作者:[Jason Baker][a] +译者:[ZH1122](https://github.com/ZH1122) +校对:[wxy](https://github.com/wxy) + +本文由 [LCTT](https://github.com/LCTT/TranslateProject) 原创编译,[Linux中国](https://linux.cn/) 荣誉推出 + +[a]:https://opensource.com/users/jason-baker +[1]:https://opensource.com/resources/python?intcmp=7016000000127cYAAQ +[2]:https://opensource.com/resources/python/ides?intcmp=7016000000127cYAAQ +[3]:https://opensource.com/resources/python/gui-frameworks?intcmp=7016000000127cYAAQ +[4]:https://opensource.com/tags/python?intcmp=7016000000127cYAAQ +[5]:https://developers.redhat.com/?intcmp=7016000000127cYAAQ +[6]:https://github.com/chineking/cola +[7]:https://github.com/matiasb/demiurge +[8]:https://github.com/kurtmckee/feedparser +[9]:https://github.com/michaelhelmick/lassie +[10]:https://github.com/jmcarp/robobrowser +[11]:https://opensource.com/resources/python/web-scraper-crawler?imm_mid=0f7103&cmp=em-prog-na-na-newsltr_20171007&rate=Wn1vUb9FpPK-IGQ1waRzgdIsDN3pXBH6rO2xnjoK_t4 +[12]:https://opensource.com/user/19894/feed +[13]:https://www.flickr.com/photos/youasamachine/8025582590/in/photolist-decd6C-7pkccp-aBfN9m-8NEffu-3JDbWb-aqf5Tx-7Z9MTZ-rnYTRu-3MeuPx-3yYwA9-6bSLvd-irmvxW-5Asr4h-hdkfCA-gkjaSQ-azcgct-gdV5i4-8yWxCA-9G1qDn-5tousu-71V8U2-73D4PA-iWcrTB-dDrya8-7GPuxe-5pNb1C-qmnLwy-oTxwDW-3bFhjL-f5Zn5u-8Fjrua-bxcdE4-ddug5N-d78G4W-gsYrFA-ocrBbw-pbJJ5d-682rVJ-7q8CbF-7n7gDU-pdfgkJ-92QMx2-aAmM2y-9bAGK1-dcakkn-8rfyTz-aKuYvX-hqWSNP-9FKMkg-dyRPkY +[14]:https://creativecommons.org/licenses/by/2.0/ +[15]:http://www.robotstxt.org/ +[16]:https://github.com/binux/pyspider +[17]:http://docs.pyspider.org/en/latest/ +[18]:http://demo.pyspider.org/ +[19]:https://github.com/hickford/MechanicalSoup +[20]:https://www.crummy.com/software/BeautifulSoup/ +[21]:https://github.com/hickford/MechanicalSoup/blob/master/example.py +[22]:https://scrapy.org/ +[23]:https://doc.scrapy.org/en/latest/ +[24]:https://scrapy.org/community/ +[25]:https://github.com/scrapy/scrapy +[26]:https://github.com/scrapinghub/portia +[27]:https://portia.scrapinghub.com/ +[28]:https://selenium-python.readthedocs.io/ +[29]:https://github.com/SeleniumHQ/selenium +[30]:https://opensource.com/users/jason-baker +[31]:https://opensource.com/users/jason-baker +[32]:https://opensource.com/resources/python/web-scraper-crawler?imm_mid=0f7103&cmp=em-prog-na-na-newsltr_20171007#comments +[33]:https://en.wikipedia.org/wiki/Web_crawler +[34]:https://en.wikipedia.org/wiki/Web_scraping diff --git a/published/201710/20160511 LEDE and OpenWrt.md b/published/201710/20160511 LEDE and OpenWrt.md new file mode 100644 index 0000000000..4465127280 --- /dev/null +++ b/published/201710/20160511 LEDE and OpenWrt.md @@ -0,0 +1,95 @@ +LEDE 和 OpenWrt 分裂之争 +=================== + +对于家用 WiFi 路由器和接入点来说,[OpenWrt][1] 项目可能是最广为人知的 Linux 发行版;在 12 年以前,它产自现在有名的 Linksys WRT54G 路由器的源代码。(2016 年)五月初,当一群 OpenWrt 核心开发者 [宣布][2] 他们将开始着手 OpenWrt 的一个副产品 (或者,可能算一个分支)叫 [Linux 嵌入开发环境][3] (LEDE)时,OpenWrt 用户社区陷入一片巨大的混乱中。为什么产生分裂对公众来说并不明朗,而且 LEDE 宣言惊到了一些其他 OpenWrt 开发者也暗示这团队的内部矛盾。 + +LEDE 宣言被 Jo-Philipp Wich 于五月三日发往所有 OpenWrt 开发者列表和新 LEDE 开发者列表。它将 LEDE 描述为“OpenWrt 社区的一次重启” 和 “OpenWrt 项目的一个副产品” ,希望产生一个 “注重透明性、合作和权利分散”的 Linux 嵌入式开发社区。 + +给出的重启的原因是 OpenWrt 遭受着长期以来存在且不能从内部解决的问题 —— 换句话说,关于内部处理方式和政策。例如,宣言称,开发者的数目在不断减少,却没有接纳新开发者的方式(而且貌似没有授权委托访问给新开发者的方法)。宣言说到,项目的基础设施不可靠(例如,去年服务器挂掉在这个项目中也引发了相当多的矛盾),但是内部不合和单点错误阻止了修复它。内部和从这个项目到外面世界也存在着“交流、透明度和合作”的普遍缺失。最后,一些技术缺陷被引述:不充分的测试、缺乏常规维护,以及窘迫的稳固性与文档。 + +该宣言继续描述 LEDE 重启将怎样解决这些问题。所有交流频道都会打开供公众使用,决策将在项目范围内的投票决出,合并政策将放宽等等。更详细的说明可以在 LEDE 站点的[规则][4]页找到。其他细节中,它说贡献者将只有一个阶级(也就是,没有“核心开发者”这样拥有额外权利的群体),简单的少数服从多数投票作出决定,并且任何被这个项目管理的基础设施必须有三个以上管理员账户。在 LEDE 邮件列表, Hauke Mehrtens [补充][5]到,该项目将会努力把补丁投递到上游项目 —— 这是过去 OpenWrt 被批判的一点,尤其是对 Linux 内核。 + +除了 Wich,这个宣言被 OpenWrt 贡献者 John Crispin、 Daniel Golle、 Felix Fietkau、 Mehrtens、 Matthias Schiffer 和 Steven Barth 共同签署,并以给其他有兴趣参与的人访问 LEDE 站点的邀请作为了宣言结尾。 + +### 回应和问题 + +有人可能会猜想 LEDE 组织者预期他们的宣言会有或积极或消极的反响。毕竟,细读宣言中批判 OpenWrt 项目暗示了 LEDE 阵营发现有一些 OpenWrt 项目成员难以共事(例如,“单点错误” 或 “内部不和”阻止了基础设施的修复)。 + +并且,确实,有很多消极回应。OpenWrt 创立者之一 Mike Baker [回应][6] 了一些警告,反驳所有 LEDE 宣言中的结论并称“像‘重启’这样的词语都是含糊不清的,且具有误导性的,而且 LEDE 项目未能揭晓其真实本质。”与此同时,有人关闭了那些在 LEDE 宣言上署名的开发者的 @openwrt.org 邮件入口;当 Fietkau [提出反对][7], Baker [回复][8]账户“暂时停用”是因为“还不确定 LEDE 能不能代表 OpenWrt。” 另一个 OpenWrt 核心成员 Imre Kaloz [写][9]到,他们现在所抱怨的 OpenWrt 的“大多数[破]事就是 LEDE 团队弄出来的”。 + +但是大多数 OpenWrt 列表的回应对该宣言表示困惑。邮件列表成员不明确 LEDE 团队是否将对 OpenWrt [继续贡献][10],或导致了这次分裂的架构和内部问题的[确切本质][11]是什么。 Baker 的第一反应是对宣言中引述的那些问题缺乏公开讨论表示难过:“我们意识到当前的 OpenWrt 项目遭受着许多的问题,”但“我们希望有机会去讨论并尝试着解决”它们。 Baker 作出结论: + +> 我们想强调,我们确实希望能够公开的讨论,并解决掉手头事情。我们的目标是与所有能够且希望对 OpenWrt 作出贡献的参与者共事,包括 LEDE 团队。 + +除了有关新项目的初心的问题之外,一些邮件列表订阅者提出了 LEDE 是否与 OpenWrt 有相同的使用场景定位,给新项目取一个听起来更一般的名字的疑惑。此外,许多人,像 Roman Yeryomin,对为什么这些问题需要 LEDE 团队的离开(来解决)[表示了疑惑][12],特别是,与此同时,LEDE 团队由大部分活跃核心 OpenWrt 开发者构成。一些列表订阅者,像 Michael Richardson,甚至不清楚[谁还会继续开发][13] OpenWrt。 + +### 澄清 + +LEDE 团队尝试着深入阐释他们的境况。在 Fietkau 给 Baker 的回复中,他说在 OpenWrt 内部关于有目的地改变的讨论会很快变得“有毒,”因此导致没有进展。而且: + +> 这些讨论的要点在于那些掌握着基础设施关键部分的人精力有限却拒绝他人的加入和帮助,甚至是面对无法及时解决的重要问题时也是这样。 + +> 这种像单点错误一样的事已经持续了很多年了,没有任何有意义的进展来解决它。 + +Wich 和 Fietkau 都没有明显指出具体的人,虽然在列表的其他人可能会想到这个基础设施和 OpenWrt 的内部决策问题要归咎于某些人。 Daniel Dickinson [陈述][14]到: + +> 我的印象是 Kaloz (至少) 以基础设施为胁来保持控制,并且根本性的问题是 OpenWrt 是*不*民主的,而且忽视那些真正在 OpenWrt 工作的人想要的是什么,无视他们的愿望,因为他/他们把控着要害。 + +另一方面, Luka Perkov [指出][15] 很多 OpemWrt 开发者想从 Subversion 转移到 Git,但 Fietkau 却阻止这种变化。 + +看起来是 OpenWrt 的管理结构并非如预期般发挥作用,其结果导致个人冲突爆发,而且由于没有完好定义的流程,某些人能够简单的忽视或阻止提议的变化。明显,这不是一个能长期持续的模式。 + +五月六日,Crispin 在一个新的帖子中[写给][16] OpenWrt 列表,尝试着重构 LEDE 项目宣言。他说,这并不是意味着“敌对或分裂”行为,只是与结构失衡的 OpenWrt 做个清晰的划分并以新的方式开始。问题在于“不要归咎于一次单独的事件、一个人或者一次口水战”,他说,“我们想与过去自己造成的错误和多次作出的错误管理决定分开”。 Crispin 也承认宣言没有把握好,说 LEDE 团队 “弄糟了发起纲领。” + +Crispin 的邮件似乎没能使 Kaloz 满意,她[坚持认为][17] Crispin(作为发行经理)和 Fietkau(作为领头开发者)可以轻易地在 OpenWrt 内部作出想要的改变。但是讨论的下文后来变得沉寂;之后 LEDE 或者 OpenWrt 哪边会发生什么还有待观察。 + +### 目的 + +对于那些想要探究 LEDE 所认为有问题的事情的更多细节的 OpenWrt 成员来说,有更多的信息来源可以为这个问题提供线索。在公众宣言之前,LEDE 组织花了几周谈论他们的计划,会议的 IRC 日志现已[发布][18]。特别有趣的是,三月三十日的[会议][19]包含了这个项目目标的细节讨论。 + +其中包括一些针对 OpenWrt 的基础设施的抱怨,像项目的 Trac 工单追踪器的缺点。它充斥着不完整的漏洞报告和“我也是”的评论,Wich 说,结果几乎没有贡献者使用它。此外,他们也在 Github 上追踪 bug,人们对这件事感到困惑,这使得工单应该在哪里讨论不明了。 + +这些 IRC 讨论也定下了开发流程本身。LEDE 团队想作出些改变,以使用会合并到主干的阶段开发分支为开端,与 OpenWrt 所使用的“直接提交到主干”方式不同。该项目也将提供基于时间的发行版,并通过只发行已被成功测试的二进制模块来鼓励用户测试,由社区而不是核心开发者在实际的硬件上进行测试。 + +最后,这些 IRC 讨论也确定了 LEDE 团队的目的不是用它的宣言吓唬 OpenWrt。Crispin 提到 LEDE 首先是“半公开的”并渐渐做得更公开。 Wich 解释说他希望 LEDE 是“中立的、专业的,并打开大门欢迎 OpenWrt 以便将来的合并”。不幸的是,前期发起工作并不是做得很好。 + +在一封邮件中, Fietkau 补充到 OpenWrt 核心开发者确实在任务中遇到瓶颈,像补丁复审和基础设施维护这些事情让他们完成不了其他工作,比如配置下载镜像和改良构建系统。在 LEDE 宣言之后短短几天内,他说,团队成功解决了镜像和构建系统任务,而这些已被搁置多年。 + +> 我们在 LEDE 所做的事情很多是基于转移到 Github 的去中心化软件包开发经验,并放弃了软件包应如何被维护的许多控制。这样最终有效减少了我们的工作量,而且我们有了很多更活跃的开发者。 + +> 我们真的希望为核心开发做一些类似的事,但是基于我们想作出更大改变的经验,我们觉得在 OpenWrt 项目内做不到。 + +修复基础设施也将收获其他好处,他说,就比如改进了用于管理签署发布版本的密码的系统。团队正在考虑在某些情况下非上游补丁的规则,像需要补丁的描述和为什么没有发送到上游的解释。他也提到很多留下的 OpenWrt 开发者表示有兴趣加入 LEDE,相关当事人正试图弄清楚他们是否会重新合并该项目。 + +有人希望 LEDE 更为扁平的管理模式和更为透明的分工会在困扰 OpenWrt 的方面取得成功。解决最初的宣言中被诟病的沟通方面的问题会是最大的障碍。如果那个过程处理得好,那么,未来 LEDE 和 OpenWrt 可能能够求同存异并协作。否则,之后两个团队可能一起被迫发展到比以前拥有更少资源的方向,这也许不是开发者或用户想看到的。 + +-------------------------------------------------------------------------------- + +via: https://lwn.net/Articles/686767/ + +作者:[Nathan Willis][a] +译者:[XYenChi](https://github.com/XYenChi) +校对:[wxy](https://github.com/wxy) + +本文由 [LCTT](https://github.com/LCTT/TranslateProject) 原创编译,[Linux中国](https://linux.cn/) 荣誉推出 + +[a]:https://lwn.net/Articles/686767/ +[1]:https://openwrt.org/ +[2]:https://lwn.net/Articles/686180/ +[3]:https://www.lede-project.org/ +[4]:https://www.lede-project.org/rules.html +[5]:http://lists.infradead.org/pipermail/lede-dev/2016-May/000080.html +[6]:https://lwn.net/Articles/686988/ +[7]:https://lwn.net/Articles/686989/ +[8]:https://lwn.net/Articles/686990/ +[9]:https://lwn.net/Articles/686991/ +[10]:https://lwn.net/Articles/686995/ +[11]:https://lwn.net/Articles/686996/ +[12]:https://lwn.net/Articles/686992/ +[13]:https://lwn.net/Articles/686993/ +[14]:https://lwn.net/Articles/686998/ +[15]:https://lwn.net/Articles/687001/ +[16]:https://lwn.net/Articles/687003/ +[17]:https://lwn.net/Articles/687004/ +[18]:http://meetings.lede-project.org/lede-adm/2016/?C=M;O=A +[19]:http://meetings.lede-project.org/lede-adm/2016/lede-adm.2016-03-30-11.05.log.html diff --git a/translated/tech/20160602 Building a data science portfolio - Storytelling with data.md b/published/201710/20160602 Building a data science portfolio - Storytelling with data.md similarity index 86% rename from translated/tech/20160602 Building a data science portfolio - Storytelling with data.md rename to published/201710/20160602 Building a data science portfolio - Storytelling with data.md index 281c2dee20..b7b0501bfa 100644 --- a/translated/tech/20160602 Building a data science portfolio - Storytelling with data.md +++ b/published/201710/20160602 Building a data science portfolio - Storytelling with data.md @@ -1,13 +1,11 @@ - -建立一项数据科学组合:讲一个关于数据的故事 +构建你的数据科学作品集:用数据讲故事 ======== +> 这是如何建立数据科学作品集Data Science Portfolio系列文章中的第一篇。如果你喜欢这篇文章并且想知道此系列的下一篇文章何时发表,你可以[在页面底部订阅][35]。 ->这是如何建立科学组合系列文章中的第一篇。如果你喜欢这篇文章并且想知道此系列的下一篇文章何时发表,你可以[在页面底部订阅][35]。 +数据科学公司们在决定雇佣一个人时越来越看重其作品集。其中一个原因就是作品集portfolio是分析一个人真实技能的最好方式。好消息是,作品集是完全可以被你掌控的。如果你在其上投入了一些工作,你就能够做出一个令那些公司印象深刻的作品集结果。 -数据科学公司们在采用一个想法时越来越看重组合结果。其中一个原因就是运用组合是分析一个人真实技能的最好方式。对你来说好消息解释组合是完全可以被你掌控的。如果你针对一些事情做了一些工作,你就能的奥一个令那些公司印象深刻的组合结果。 - -建立一个高质量组合的第一步就是知道展示什么技能。那些公司们主要希望数据科学工作者拥有的技能,或者说他们主要希望组合所展示的技能是: +建立一个高质量作品集的第一步就是知道展示什么技能。那些公司们主要希望数据科学工作者拥有的技能,或者说他们主要希望作品集所展示的技能是: * 表达能力 * 合作能力 @@ -15,95 +13,95 @@ * 解释数据的能力 * 有目标和有积极性的 -任何一个好的组合都由多个工程构成,每一个工程都会展示1-2个上面所说的点。这是涵盖了“如何完成一个完整的科学组合”系列文章的第一篇。在这篇文章中,我们将会涵括如何完成你的第一项数据科学组合工程,并且对此进行有效的解释。在ui后,你将会得到一个帮助展示你表达能力和解释数据能力的工程。 +任何一个好的作品集都由多个工程构成,每一个工程都会展示 1-2 个上面所说的点。这是涵盖了“如何完成一个完整的数据科学作品集”系列文章的第一篇。在这篇文章中,我们将会涵括如何完成你的第一项数据科学作品集工程,并且对此进行有效的解释。在最后,你将会得到一个帮助展示你表达能力和解释数据能力的工程。 -### 讲述一个关于数据的故事 +### 用数据讲故事 -于数据科学表达是基础。你将会发现数据的内含,并且找出一个高效的方式来向他人表达,之后向他们展示你所开展的课题。数据科学最关键的手法之一就是能够讲述一个关于使用数据的清晰的故事。一个好的故事能够使你得到的结果更加引人注目,并且能是别人理解你的想法。 +数据科学是表达的基础。你将会在数据中发现一些观点,并且找出一个高效的方式来向他人表达这些,之后向他们展示你所开展的课题。数据科学最关键的手法之一就是能够用数据讲述一个清晰的故事。一个清晰的故事能够使你的观点更加引人注目,并且能使别人理解你的想法。 -数据科学中的故事是一个讲述关于你发现了什么,你怎么发现它的,并且它意味着什么的故事。例如假使发现你公司的收入相对去年减少了百分之二十。这并不能够确定原因或者表达为什么收入会减少并且在尝试修复它。 +数据科学中的故事是一个讲述你发现了什么,你怎么发现它的,并且它意味着什么的故事。例如假使发现你公司的收入相对去年减少了百分之二十。这并不能够确定原因,你可能需要和其它人沟通为什么收入会减少,并且在尝试修复它。 -讲述关于数据的故事主要包含: +用数据讲故事主要包含: -* 理解并确定内容 -* 从多角度发觉 +* 理解并确定上下文 +* 从多角度发掘 * 使用有趣的表示方法 * 使用多种数据来源 -* 有一致的叙述 +* 一致的表述 -用来讲述关于数据的故事最有效率的工具就是[Jupyter notebook][34]。如果你不熟悉,[此处][33]有一个好的教程。 Jupyter notebook 允许你交互式的发掘数据,并且将你的结果分享到多个网站,包括Github,分享你的结果有助于合作研究和其他人拓展你的分析。 +用来讲述数据的故事最有效率的工具就是 [Jupyter notebook][34]。如果你不熟悉,[此处][33]有一个好的教程。Jupyter notebook 允许你交互式的发掘数据,并且将你的结果分享到多个网站,包括 Github。分享你的结果有助于合作研究和其他人拓展你的分析。 -我们将使用Jupyter notebook,Python库和matplotlib在这篇文章中。 +在这篇文章中,我们将使用 Jupyter notebook,以及 Pandas 和 matplotlib 这样的 Python 库。 ### 为你的数据科学工程选择一个主题 -建立一个工程的第一步就是觉得你的主题。你需要你的主题是你兴趣所在的,并且有动力去挖掘。当人们为了完成一个项目而完成和当人们完成项目是因为有兴趣去进行数据挖掘时的区别是很明显的。这个步骤是值得花费时间的,所以确保你找到了你真正感兴趣的东西。 +建立一个工程的第一步就是决定你的主题。你要让你的主题是你兴趣所在,有动力去挖掘。进行数据挖掘时,为了完成而完成和有兴趣完成的区别是很明显的。这个步骤是值得花费时间的,所以确保你找到了你真正感兴趣的东西。 -一个寻找主题的好的方法就是浏览不同的数据组并且寻找感兴趣的部分。这里有一些作为起点的好的网站: +一个寻找主题的好方法就是浏览不同的数据集并且寻找感兴趣的部分。这里有一些作为起点的好的网站: -* [Data.gov][20] - 包含了政府据。 -* [/r/datasets][19] – 一个有着上百个有趣数据组的reddit(reddit是一个类似于贴吧、论坛的网站)。 -* [Awesome datasets][18] – 一个数据组的列表,位于Github上。 -* [rs.io][17] – 一个有着上百个有趣数据组的博客。 +* [Data.gov][20] - 包含了政府数据。 +* [/r/datasets][19] – 一个有着上百个有趣数据集的 reddit 板块。 +* [Awesome datasets][18] – 一个数据集的列表,位于 Github 上。 +* [17 个找到数据集的地方][17] – 这篇博文列出了 17 个数据集,每个都包含了示例数据集。 -真实世界中的数据科学,经常无法找到合适的单个数据组。你可能需要合并多个独立的数据源,或者做数量庞大的数据清理。如果主题非常吸引你,这是值得这样做的,并且也能更好的展示你的技能。 +真实世界中的数据科学,你经常无法找到可以浏览的合适的单个数据集。你可能需要聚合多个独立的数据源,或者做数量庞大的数据清理。如果该主题非常吸引你,这是值得这样做的,并且也能更好的展示你的技能。 关于这篇文章的主题,我们将使用纽约市公立学校的数据,我们可以在[这里][32]找到它。 ### 选择主题 -对于完成项目来说这是十分重要的。因为主题能很好的限制项目的范围,并且使它能够是我们知道它可以被完成。比起一个没有足够动力完成的工程来说添加到一个完成的工程更加容易。 +这对于项目全程来说是十分重要的。因为主题能很好的限制项目的范围,并且它能够使我们知道它可以被完成。比起一个没有足够动力完成的工程来说,添加到一个完成的工程更加容易。 -所以,我们将关注高中的[学术评估测试][31],伴随着多种人口统计和它们的其它数据。关于SAT,或者说学习评估测试,是美国高中生进入大学前的测试。大学在做判定时将成绩录入账号,所以高分是十分重要的。考试分为三个阶段,每个阶段总分为800。全部分数为2400(即使这个前后更改了几次,在数据中总分还是2400)。高中经常通过平均STA分数进行排名,并且SAT是评判高中有多好的标准。 +所以,我们将关注高中的[学术评估测试][31],伴随着多种人口统计和它们的其它数据。关于学习评估测试, 或者说 SAT,是美国高中生申请大学前的测试。大学在做判定时将考虑该成绩,所以高分是十分重要的。考试分为三个阶段,每个阶段总分为 800。全部分数为 2400(即使这个前后更改了几次,在数据中总分还是 2400)。高中经常通过平均 SAT分数进行排名,并且 SAT 是评判高中有多好的标准。 -因为由关于STA分数对于美国中某些种族群体是不公平的。,所以这个纽约市数据分析能够帮助对SAT的公平性有轻许帮助。 +因为由关于 SAT 分数对于美国中某些种族群体是不公平的,所以对纽约市这个数据做分析能够对 SAT 的公平性有些许帮助。 -我们有SAT成绩的数据组[这里][30],并且数据组中包含了每所高中的信息[这里][29]。这些将总成我们的工程的基础,但是我们将将如更多的信息来创建有趣的分析。 +我们在[这里][30]有 SAT 成绩的数据集,并且在[这里][29]有包含了每所高中的信息的数据集。这些将构成我们的工程的基础,但是我们将加入更多的信息来创建有趣的分析。 ### 补充数据 -如果你已经有了一个很好的主题,拓展其它可以提升主题或者更深入挖掘数据的的数据组是被推荐的。十分适合在前期做这些工作,那么你将会有尽可能多的数据来构建你的工程。有着越少的数据意味着你太早的放弃了你的工程。 +如果你已经有了一个很好的主题,拓展其它可以提升主题或者更深入挖掘数据的的数据集是一个好的选择。在前期十分适合做这些工作,你将会有尽可能多的数据来构建你的工程。数据越少意味着你会太早的放弃了你的工程。 -在包含人口统计信息和测试成绩的网站上这里有一些相关的数据组。 +在本项目中,在包含人口统计信息和测试成绩的网站上有一些相关的数据集。 -这些是我们将会用到的所有数据组: +这些是我们将会用到的所有数据集: -* [SAT scores by school][16] – 纽约市每所高中的STA成绩。 -* [School attendance][15] – 纽约市每所学校的出勤信息。 -* [Math test results][14] – 纽约市每所学校的数学成绩。 -* [Class size][13] - 纽约市每所学校课堂人数信息。 -* [AP test results][12] – Advanced Placement exam results for each high school. Passing AP exams can get you college credit in the US. -* [AP test results][12] - 高阶位考试,在美国,通过AP测试就能获得大学学分。 -译者注:高阶位考试(AP)是美国和加拿大的一个由大学委员会创建的计划,该计划为高中学生提供大学水平的课程和考试。 美国学院和大学可以授予在考试中获得高分的学生的就学和课程学分。 +* [学校 SAT 成绩][16] – 纽约市每所高中的 SAT 成绩。 +* [学校出勤情况][15] – 纽约市每所学校的出勤信息。 +* [数学成绩][14] – 纽约市每所学校的数学成绩。 +* [班级规模][13] - 纽约市每所学校课堂人数信息。 +* [AP 成绩][12] - 高阶位考试,在美国,通过 AP 测试就能获得大学学分。 +* [毕业去向][11] – 由百分之几的学生毕业了,和其它去向信息。 +* [人口统计][10] – 每个学校的人口统计信息。 +* [学校问卷][9] – 学校的家长、教师,学生的问卷。 +* [学校分布地图][8] – 包含学校的区域布局信息,因此我们能将它们在地图上标出。 -* [Graduation outcomes][11] – 由百分之几的学生毕业了,和其它去向信息。 -* [Demographics][10] – 每个学校的人口统计信息。 -* [School survey][9] – 学校的家长、教师,学生的问卷。 -* [School district maps][8] – 包含学校的区域布局信息,因此我们能将它们在地图上标出。 +(LCTT 译注:高阶位考试(AP)是美国和加拿大的一个由大学委员会创建的计划,该计划为高中学生提供大学水平的课程和考试。 美国学院和大学可以授予在考试中获得高分的学生的就学和课程学分。) -这些数据组合之间是相互关联的,并且我们能够在开始分析之前进行合并。 +这些数据作品集之间是相互关联的,并且我们能够在开始分析之前进行合并。 ### 获取背景信息 在开始分析数据之前,搜索一些背景信息是有必要的。我们知道这些有用的信息: * 纽约市被分为五个不同的辖区 -* 纽约市的学校坐落在学校区域内,每个都学校区域都可能包含数十所学校。 -* 数据组中的并不全是高中,所以我们需要对数据进行一些清理工作。 -* 纽约市的每所学校都有自己单独的编码,被称为‘DBN’,或者区域行政编号。 -* 为了通过区域进行合并数据,我们可以使用地图区域信息来绘制逐区差异。 +* 纽约市的学校被分配到几个学区,每个学区都可能包含数十所学校。 +* 数据集中的学校并不全是高中,所以我们需要对数据进行一些清理工作。 +* 纽约市的每所学校都有自己单独的编码,被称为‘DBN’,即区域行政编号。 +* 为了通过区域进行数据聚合,我们可以使用地图区域信息来绘制逐区差异。 ### 理解数据 -为了真正的理解数据信息,你将需要花费时间挖掘和阅读数据。因此,每一个数据链接的描述信息都沿着相关列。假如我们拥有高中SAT成绩信息,包含图像和其它信息的数据组。 +为了真正的理解数据信息,你需要花费时间来挖掘和阅读数据。因此,每个数据链接都有数据的描述信息,并伴随着相关列。就像是我们拥有的高中 SAT 成绩信息,也包含图像和其它信息的数据集。 -我们可以运行一些代码来读取数据。我们将使用[Jupyter notebook][28]来挖掘数据。下面的代码将会执行一下操作: +我们可以运行一些代码来读取数据。我们将使用 [Jupyter notebook][28] 来挖掘数据。下面的代码将会执行以下操作: -* 循环通过我们下载的所有数据文件。 -* 将文件读取到[Pandas DataFrame][7]。 -* 将所有数据框架导入Python数据库中。 +* 循环遍历我们下载的所有数据文件。 +* 将文件读取到 [Pandas DataFrame][7]。 +* 将所有数据框架导入 Python 数据库中。 + +In \[100]: -In [100]: ``` import pandas import numpy as np @@ -114,17 +112,16 @@ data = {} for f in files: d = pandas.read_csv("schools/{0}".format(f)) data[f.replace(".csv", "")] = d - ``` -一旦我们将数据读入,我们就可以使用数据框架中的[头部][27]方法打印每个数据框架的前五行。 +一旦我们将数据读入,我们就可以使用 DataFrames 的 [head][27] 方法打印每个 DataFrame 的前五行。 + +In \[103]: -In [103]: ``` for k,v in data.items(): print("\n" + k + "\n") print(v.head()) - ``` ``` @@ -378,34 +375,31 @@ hs_directory 4 160-20 Goethals Avenue\nJamaica, NY 11432\n(40... [5 rows x 58 columns] - ``` -我们可以开始在数据组合中观察有用的部分: +我们可以开始在数据作品集中观察有用的部分: -* Most of the datasets contain a `DBN` column -* 大部分数据组包含DBN列。 -* 一些条目看起来在地图上标出会很有趣,特别是`Location 1`,这列对应的信息会多一些。 -* 有些数据组会出现每所学校对应多行数据(DBN数据重复),这意味着我们要进行预处理。 +* 大部分数据集包含 DBN 列。 +* 一些条目看起来在地图上标出会很有趣,特别是 `Location 1`,这列在一个很长的字符串里面包含了位置信息。 +* 有些数据集会出现每所学校对应多行数据(DBN 数据重复),这意味着我们要进行预处理。 -### Unifying the data ### 统一数据 -为了使工作更简单,我们将需要将全部零散的数据组统一为一个。这将使我们能够快速跨数据组对比数据列。因此,我们需要找到相同的列将他们统一起来。请查看上面的输出数据,当DBN出现在多个数据组中时它很可能成为共同列。 +为了使工作更简单,我们将需要将全部零散的数据集统一为一个。这将使我们能够快速跨数据集对比数据列。因此,我们需要找到相同的列将它们统一起来。请查看上面的输出数据, DBN 出现在多个数据集中,它看起来可以作为共同列。 -如果我们用google搜索`DBN New York City Schools`, 我们[在此][26]得到了结果。它解释了DBN是每个学校独特的编码。我们将挖掘数据组,特别是政府数据组。这通常需要做一些工作来找出每列的含义,或者每个数据组是的意图。 +如果我们用 google 搜索 `DBN New York City Schools`,我们[在此][26]得到了结果。它解释了 DBN 是每个学校独特的编码。我们将挖掘数据集,特别是政府数据集。这通常需要做一些工作来找出每列的含义,或者每个数据集的意图。 -现在这两个数据组的主要的问题是,`class_size`, 和 `hs_directory`数据组, 没有 `DBN` 列。在`hs_directory` 数据中是dbn,那么我们只需重命名即可,或者将它复制到新的名为DBN的列中。在`class_size`数据中,我们将需要尝试不同的方法。 +现在主要的问题是这两个数据集 `class_size` 和 `hs_directory`,没有 `DBN` 列。在 `hs_directory` 数据中是 `dbn`,那么我们只需重命名即可,或者将它复制到新的名为 DBN 的列中。在 `class_size` 数据中,我们将需要尝试不同的方法。 DBN列: -In [5]: +In \[5]: + ``` data["demographics"]["DBN"].head() - ``` -Out[5]: +Out\[5]: ``` 0 01M015 1 01M015 @@ -415,15 +409,15 @@ Out[5]: Name: DBN, dtype: object ``` -如果我们看向`class_size`数据,我们将看到前五行: +如果我们查看 `class_size`数据,我们将看到前五行如下: + +In \[4]: -In [4]: ``` data["class_size"].head() - ``` -Out[4]: +Out\[4]: | | CSD | BOROUGH | SCHOOL CODE | SCHOOL NAME | GRADE | PROGRAM TYPE | CORE SUBJECT (MS CORE and 9-12 ONLY) | CORE COURSE (MS CORE and 9-12 ONLY) | SERVICE CATEGORY(K-9* ONLY) | NUMBER OF STUDENTS / SEATS FILLED | NUMBER OF SECTIONS | AVERAGE CLASS SIZE | SIZE OF SMALLEST CLASS | SIZE OF LARGEST CLASS | DATA SOURCE | SCHOOLWIDE PUPIL-TEACHER RATIO | | ---- | ---- | ------- | ----------- | ------------------------- | ----- | ------------ | ------------------------------------ | ----------------------------------- | --------------------------- | --------------------------------- | ------------------ | ------------------ | ---------------------- | --------------------- | ----------- | ------------------------------ | @@ -433,46 +427,45 @@ Out[4]: | 3 | 1 | M | M015 | P.S. 015 Roberto Clemente | 01 | CTT | - | - | - | 17.0 | 1.0 | 17.0 | 17.0 | 17.0 | ATS | NaN | | 4 | 1 | M | M015 | P.S. 015 Roberto Clemente | 02 | GEN ED | - | - | - | 15.0 | 1.0 | 15.0 | 15.0 | 15.0 | ATS | NaN | -正如上面所见,DBN实际上是`CSD`, `BOROUGH`, 和 `SCHOOL CODE` 的组合。对那些不熟悉纽约市的人来说,纽约由五个行政区组成。每个行政区是一个组织团体,并且有着美国城市一样的面积。DBN全称为行政区域编号。看起来就像CSD是区域,BOROUGH是行政区,并且当与SCHOOL CODE合并时就组成了DBN。这里并没有系统的方法寻找像这个数据这样的内在规律,并且这需要一些探索和努力来发现。 +正如上面所见,DBN 实际上是 `CSD`、 `BOROUGH` 和 `SCHOOL CODE` 的组合。对那些不熟悉纽约市的人来说,纽约由五个行政区组成。每个行政区是一个组织单位,并且有着相当于美国大城市一样的面积。DBN 全称为行政区域编号。看起来就像 CSD 是区域,BOROUGH 是行政区,并且当与 SCHOOL CODE 合并时就组成了 DBN。这里并没有寻找像这个数据这样的内在规律的系统方法,这需要一些探索和努力来发现。 -现在我们已经知道了DBN的组成,那么我们就可以将它加入到class_size和hs_directory数据组中了: +现在我们已经知道了 DBN 的组成,那么我们就可以将它加入到 `class_size` 和 `hs_directory` 数据集中了: + +In \[ ]: -In [ ]: ``` data["class_size"]["DBN"] = data["class_size"].apply(lambda x: "{0:02d}{1}".format(x["CSD"], x["SCHOOL CODE"]), axis=1) data["hs_directory"]["DBN"] = data["hs_directory"]["dbn"] - ``` -### 加入问卷 +#### 加入问卷 -最可能值得一看的数据组之一就是学生、家长和老师关于学校质量的问卷了。这些问卷包含了每所学校的安全度,教学水平等。之前我们所合并了数据组,让我们们添加问卷数据。在真实世界的数据科学工程中,你将要经常会在分析过程中碰到有趣的数据,并且希望合并它。使用灵活的工具就像Jupyter notebook 将允许你快速添加一些新的代码,并且重新开始你的分析。 +最可能值得一看的数据集之一就是学生、家长和老师关于学校质量的问卷了。这些问卷包含了每所学校的安全程度、教学水平等。在我们合并数据集之前,让我们添加问卷数据。在真实世界的数据科学工程中,你经常会在分析过程中碰到有趣的数据,并且希望合并它。使用像 Jupyter notebook 一样灵活的工具将允许你快速添加一些新的代码,并且重新开始你的分析。 -因此,我们将添加问卷数据到我们的data文件夹,并且合并所有之前的数据。问卷数据分为两个文件,一个包含所有的学校,一个包含75号区域的学校。我们将需要写一些代码来合并它们。之后的代码我们将: +因此,我们将添加问卷数据到我们的 data 文件夹,并且合并所有之前的数据。问卷数据分为两个文件,一个包含所有的学校,一个包含 75 学区。我们将需要写一些代码来合并它们。之后的代码我们将: -* 读取所有学校的问卷,并使用windows-1252作为编码。 -* 使用windows-1252编码读取所有75号区域学校的问卷。 -* 添加标签来表明每个数据组包含哪个区域的学校。 -* 使用数据框架[concat][6]方法合并数据组为一个。 +* 使用 windows-1252 编码读取所有学校的问卷。 +* 使用 windows-1252 编码读取所有 75 号学区的问卷。 +* 添加指示每个数据集所在学区的标志。 +* 使用 DataFrame 的 [concat][6] 方法将数据集合并为一个。 + +In \[66]: -In [66]: ``` survey1 = pandas.read_csv("schools/survey_all.txt", delimiter="\t", encoding='windows-1252') survey2 = pandas.read_csv("schools/survey_d75.txt", delimiter="\t", encoding='windows-1252') survey1["d75"] = False survey2["d75"] = True survey = pandas.concat([survey1, survey2], axis=0) - ``` -一旦我们将问卷合并,这里将会有一些混乱。我们希望我们合并的数据组列数最少,那么我们将可以轻易的进行列之间的对比并找出期间的关联。不幸的是,问卷数据有很多列并不是很有用: +一旦我们将问卷合并,这里将会有一些混乱。我们希望我们合并的数据集列数最少,那么我们将可以轻易的进行列之间的对比并找出其间的关联。不幸的是,问卷数据有很多列并不是很有用: -In [16]: +In \[16]: ``` survey.head() - ``` -Out[16]: +Out\[16]: | | N_p | N_s | N_t | aca_p_11 | aca_s_11 | aca_t_11 | aca_tot_11 | bn | com_p_11 | com_s_11 | ... | t_q8c_1 | t_q8c_2 | t_q8c_3 | t_q8c_4 | t_q9 | t_q9_1 | t_q9_2 | t_q9_3 | t_q9_4 | t_q9_5 | | ---- | ----- | ----- | ---- | -------- | -------- | -------- | ---------- | ---- | -------- | -------- | ---- | ------- | ------- | ------- | ------- | ---- | ------ | ------ | ------ | ------ | ------ | @@ -488,9 +481,10 @@ Out[16]: ![](https://www.dataquest.io/blog/images/misc/xj5ud4r.png) -我们可以去除`survey`数据组中多余的列: +我们可以去除 `survey` 数据集中多余的列: + +In \[17]: -In [17]: ``` survey["DBN"] = survey["dbn"] survey_fields = ["DBN", "rr_s", "rr_t", "rr_p", "N_s", "N_t", "N_p", "saf_p_11", "com_p_11", "eng_p_11", "aca_p_11", "saf_t_11", "com_t_11", "eng_t_10", "aca_t_11", "saf_s_11", "com_s_11", "eng_s_11", "aca_s_11", "saf_tot_11", "com_tot_11", "eng_tot_11", "aca_tot_11",] @@ -500,24 +494,24 @@ survey.shape ``` -Out[17]: +Out\[17]: + ``` (1702, 23) ``` -请确保理你已经了解了每个数据组的内容和相关联的列,者能节约你之后大量的时间和精力: +请确保理你已经了解了每个数据集的内容和相关联的列,这能节约你之后大量的时间和精力: -### 精简数据组 +### 精简数据集 -如果我们看向某些数据组,包括`class_size`,我们将立刻发现问题: +如果我们查看某些数据集,包括 `class_size`,我们将立刻发现问题: -In [18]: +In \[18]: ``` data["class_size"].head() - ``` -Out[18]: +Out\[18]: | | CSD | BOROUGH | SCHOOL CODE | SCHOOL NAME | GRADE | PROGRAM TYPE | CORE SUBJECT (MS CORE and 9-12 ONLY) | CORE COURSE (MS CORE and 9-12 ONLY) | SERVICE CATEGORY(K-9* ONLY) | NUMBER OF STUDENTS / SEATS FILLED | NUMBER OF SECTIONS | AVERAGE CLASS SIZE | SIZE OF SMALLEST CLASS | SIZE OF LARGEST CLASS | DATA SOURCE | SCHOOLWIDE PUPIL-TEACHER RATIO | DBN | | ---- | ---- | ------- | ----------- | ------------------------- | ----- | ------------ | ------------------------------------ | ----------------------------------- | --------------------------- | --------------------------------- | ------------------ | ------------------ | ---------------------- | --------------------- | ----------- | ------------------------------ | ------ | @@ -527,15 +521,15 @@ Out[18]: | 3 | 1 | M | M015 | P.S. 015 Roberto Clemente | 01 | CTT | - | - | - | 17.0 | 1.0 | 17.0 | 17.0 | 17.0 | ATS | NaN | 01M015 | | 4 | 1 | M | M015 | P.S. 015 Roberto Clemente | 02 | GEN ED | - | - | - | 15.0 | 1.0 | 15.0 | 15.0 | 15.0 | ATS | NaN | 01M015 | -每所高中都有许多行(正如你所见的重复的`DBN`和`SCHOOL NAME`)。然而,如果我们看向`sat_result`数据组,每所高中只有一行: +每所高中都有许多行(正如你所见的重复的 `DBN` 和 `SCHOOL NAME`)。然而,如果我们看向 `sat_result` 数据集,每所高中只有一行: + +In \[21]: -In [21]: ``` data["sat_results"].head() - ``` -Out[21]: +Out\[21]: | | DBN | SCHOOL NAME | Num of SAT Test Takers | SAT Critical Reading Avg. Score | SAT Math Avg. Score | SAT Writing Avg. Score | | ---- | ------ | ---------------------------------------- | ---------------------- | ------------------------------- | ------------------- | ---------------------- | @@ -545,14 +539,15 @@ Out[21]: | 3 | 01M458 | FORSYTH SATELLITE ACADEMY | 7 | 414 | 401 | 359 | | 4 | 01M509 | MARTA VALLE HIGH SCHOOL | 44 | 390 | 433 | 384 | -为了合并这些数据组,我们将需要找到方法精简数据组到如`class_size`般一行对应一所高中。否则,我们将不能将SAT成绩与班级大小进行比较。我们通过先更好的理解数据,然后做一些合并来完成。`class_size`数据组像`GRADE`和`PROGRAM TYPE`,每个学校有多个数据对应。为了将每个范围内的数据变为一个数据,我们将大部分重复行过滤掉,在下面的代码中我们将会: +为了合并这些数据集,我们将需要找到方法将数据集精简到如 `class_size` 般一行对应一所高中。否则,我们将不能将 SAT 成绩与班级大小进行比较。我们通过首先更好的理解数据,然后做一些合并来完成。`class_size` 数据集像 `GRADE` 和 `PROGRAM TYPE`,每个学校有多个数据对应。为了将每个范围内的数据变为一个数据,我们将大部分重复行过滤掉,在下面的代码中我们将会: -* 只从`class_size`中选择`GRADE`范围为`09-12`的行。 -* 只从`class_size`中选择`PROGRAM TYPE`是`GEN ED`的值。 -* 将`class_size`以`DBN`分组,然后取每列的平均值。重要的是,我们将找到每所学校班级大小平均值。 -* 重置索引,将`DBN`重新加到列中。 +* 只从 `class_size` 中选择 `GRADE` 范围为 `09-12` 的行。 +* 只从 `class_size` 中选择 `PROGRAM TYPE` 是 `GEN ED` 的行。 +* 将 `class_size` 以 `DBN` 分组,然后取每列的平均值。重要的是,我们将找到每所学校班级大小(`class_size`)平均值。 +* 重置索引,将 `DBN` 重新加到列中。 + +In \[68]: -In [68]: ``` class_size = data["class_size"] class_size = class_size[class_size["GRADE "] == "09-12"] @@ -560,82 +555,81 @@ class_size = class_size[class_size["PROGRAM TYPE"] == "GEN ED"] class_size = class_size.groupby("DBN").agg(np.mean) class_size.reset_index(inplace=True) data["class_size"] = class_size - ``` -### 精简其它数据组 +#### 精简其它数据集 -接下来,我们将需要精简`demographic`数据组。这里有每个学校收集多年的数据,所以这里每所学校有许多重复的行。我们将只选取`schoolyear`最近的可用行: +接下来,我们将需要精简 `demographic` 数据集。这里有每个学校收集多年的数据,所以这里每所学校有许多重复的行。我们将只选取 `schoolyear` 最近的可用行: -In [69]: +In \[69]: ``` demographics = data["demographics"] demographics = demographics[demographics["schoolyear"] == 20112012] data["demographics"] = demographics - ``` -我们需要精简`math_test_results` 数据组。这个数据组被`Grade`和`Year`划分。我们将只选取一年选取一个年级。 +我们需要精简 `math_test_results` 数据集。这个数据集被 `Grade` 和 `Year` 划分。我们将只选取单一学年的一个年级。 + +In \[70]: -In [70]: ``` data["math_test_results"] = data["math_test_results"][data["math_test_results"]["Year"] == 2011] data["math_test_results"] = data["math_test_results"][data["math_test_results"]["Grade"] == '8'] - ``` 最后,`graduation`需要被精简: -In [71]: +In \[71]: + ``` data["graduation"] = data["graduation"][data["graduation"]["Cohort"] == "2006"] data["graduation"] = data["graduation"][data["graduation"]["Demographic"] == "Total Cohort"] - ``` -在完成工程的主要部分之前数据清理和挖掘是十分重要的。有一个高质量的,一致的数据组将会使你的分析更加快速。 +在完成工程的主要部分之前数据清理和挖掘是十分重要的。有一个高质量的,一致的数据集将会使你的分析更加快速。 ### 计算变量 -计算变量可以通过使我们的比较更加快速来加快分析速度,并且能是我们做到本无法做到的比较。我们能做的第一件事就是从分开的列`SAT Math Avg. Score`, `SAT Critical Reading Avg. Score`, and `SAT Writing Avg. Score`计算SAT成绩: +计算变量可以通过使我们的比较更加快速来加快分析速度,并且能使我们做到本无法做到的比较。我们能做的第一件事就是从分开的列 `SAT Math Avg. Score`,`SAT Critical Reading Avg. Score` 和 `SAT Writing Avg. Score` 计算 SAT 成绩: -* 将SAT列数值从字符转转化为数字。 -* 将所有列相加以得到`sat_score`,即SAT成绩。 +* 将 SAT 列数值从字符转化为数字。 +* 将所有列相加以得到 `sat_score`,即 SAT 成绩。 + +In \[72]: -In [72]: ``` cols = ['SAT Math Avg. Score', 'SAT Critical Reading Avg. Score', 'SAT Writing Avg. Score'] for c in cols: data["sat_results"][c] = data["sat_results"][c].convert_objects(convert_numeric=True) data['sat_results']['sat_score'] = data['sat_results'][cols[0]] + data['sat_results'][cols[1]] + data['sat_results'][cols[2]] - ``` -接下来,我们将需要进行每所学校一致区域分析,所以我们将制作地图。这将是我们画出每所学校的位置,下面的代码,我们将会: +接下来,我们将需要进行每所学校的坐标位置分析,以便我们制作地图。这将使我们画出每所学校的位置。在下面的代码中,我们将会: -* 从`Location 1`列分析出经度和维度。 -* 转化`lat`(经度)和`lon`(维度)为数字。 +* 从 `Location 1` 列分析出经度和维度。 +* 转化 `lat`(经度)和 `lon`(维度)为数字。 + +In \[73]: -In [73]: ``` data["hs_directory"]['lat'] = data["hs_directory"]['Location 1'].apply(lambda x: x.split("\n")[-1].replace("(", "").replace(")", "").split(", ")[0]) data["hs_directory"]['lon'] = data["hs_directory"]['Location 1'].apply(lambda x: x.split("\n")[-1].replace("(", "").replace(")", "").split(", ")[1]) for c in ['lat', 'lon']: data["hs_directory"][c] = data["hs_directory"][c].convert_objects(convert_numeric=True) - ``` -现在,我们将输出每个数据组来查看我们有了什么数据: +现在,我们将输出每个数据集来查看我们有了什么数据: + +In \[74]: -In [74]: ``` for k,v in data.items(): print(k) print(v.head()) - ``` + ``` math_test_results DBN Grade Year Category Number Tested Mean Scale Score \ @@ -862,23 +856,23 @@ hs_directory 4 28Q680 40.718810 -73.806500 [5 rows x 61 columns] - ``` -### 合并数据组 +### 合并数据集 -现在我们已经完成了全部准备工作,我们可以用`DBN`列将数据组合并在一起了。在最后,我们将会从原始数据组得到一个有着上百列的数据组。当我们合并它们。请注意有些数据组中会没有`sat_result`中出现的高中。为了解决这个问题,我们需要使用`outer`方法来合并缺少行的数据组,这样我们就不会丢失数据。在实际分析中,缺少数据是很常见的。能够展示解释和解决数据缺失的能力是科学投资组合的重要部分。 +现在我们已经完成了全部准备工作,我们可以用 `DBN` 列将数据组合在一起了。最终,我们将会从原始数据集得到一个有着上百列的数据集。当我们合并它们,请注意有些数据集中会丢失了 `sat_result` 中出现的高中。为了解决这个问题,我们需要使用 `outer` 方法来合并缺少行的数据集,这样我们就不会丢失数据。在实际分析中,缺少数据是很常见的。能够展示解释和解决数据缺失的能力是构建一个作品集的重要部分。 -你可以在[此][25]阅读关于不同类型的join。 +你可以在[此][25]阅读关于不同类型的合并。 接下来的代码,我们将会: -* 循环通过`data`文件夹中的每一个条目。 -* 输出条目中的DBN码。 -* 决定join类别 - `inner`或`outer`。 -* 使用`DBN`列将条目合并到数据框架`full`中。 +* 循环遍历 `data` 文件夹中的每一个条目。 +* 输出条目中的非唯一的 DBN 码数量。 +* 决定合并策略 - `inner` 或 `outer`。 +* 使用 `DBN` 列将条目合并到 DataFrame `full` 中。 + +In \[75]: -In [75]: ``` flat_data_names = [k for k,v in data.items()] flat_data = [data[k] for k in flat_data_names] @@ -894,8 +888,8 @@ for i, f in enumerate(flat_data[1:]): full = full.merge(f, on="DBN", how=join_type) full.shape - ``` + ``` survey 0 @@ -911,29 +905,20 @@ graduation 0 hs_directory 0 - ``` -Out[75]: +Out\[75]: + ``` (374, 174) ``` -### 喜欢这篇文章?通过数据查询学习数据科学! - -##### - -* 从浏览器舒适的学习。 -* 使用实际的数据组。 -* 建立科学组合工程。 - -[开始免费][5] - ### 添加值 -现在我们有了我们的`full`数据框架,我们几乎拥有分析需要的所有数据。虽然这里有一些缺少的部分。我们可能将[AP][24] 考试结果与 SAT 成绩相关联,但是我们首先需要将这些列转化为数字,然后填充缺失的数据。 +现在我们有了我们的 `full` 数据框架,我们几乎拥有分析需要的所有数据。虽然这里有一些缺少的部分。我们可能将[AP][24] 考试结果与 SAT 成绩相关联,但是我们首先需要将这些列转化为数字,然后填充缺失的数据。 + +In \[76]: -In [76]: ``` cols = ['AP Test Takers ', 'Total Exams Taken', 'Number of Exams with scores 3 4 or 5'] @@ -941,36 +926,34 @@ for col in cols: full[col] = full[col].convert_objects(convert_numeric=True) full[cols] = full[cols].fillna(value=0) - ``` -然后我们将需要计算表示哦学校所在区域的`school_dist`列。这将是我们匹配学校区域并且使用我们之前下载的区域地图画出地区级别的地图。 +然后我们将需要计算表示学校所在学区的 `school_dist`列。这将是我们匹配学区并且使用我们之前下载的区域地图画出地区级别的地图。 -In [77]: +In \[77]: ``` full["school_dist"] = full["DBN"].apply(lambda x: x[:2]) - ``` -最终,我们将需要用列的平均值填充缺失的数据到`full`中。那么我们就可以计算关联了: +最终,我们将需要用该列的平均值填充缺失的数据到 `full` 中。那么我们就可以计算关联了: -In [79]: +In \[79]: ``` full = full.fillna(full.mean()) - ``` ### 计算关联 -一个好的方法来挖掘数据并查看哪些列与你所关心的问题有联系就是计算关联。这将告诉你哪列与你所关心的列更加有关联。你可以通过Pandas DataFrame 的[corr][23]方法来完成。越接近0则关联越小。越接近1则正相关越强,越接近-1则负关联越强: +一个挖掘数据并查看哪些列与你所关心的问题有联系的好方法来就是计算关联。这将告诉你哪列与你所关心的列更加有关联。你可以通过 Pandas DataFrames 的 [corr][23] 方法来完成。越接近 0 则关联越小。越接近 1 则正相关越强,越接近 -1 则负关联越强: + +In \[80]: -In [80]: ``` full.corr()['sat_score'] - ``` -Out[80]: +Out\[80]: + ``` Year NaN Number Tested 8.127817e-02 @@ -1038,25 +1021,26 @@ Name: sat_score, dtype: float64 这给了我们一些我们需要探索的内在规律: -* total_enrollment 与 `sat_score`强烈相关,这是令人惊讶的,因为你曾经认为越小的学校越专注与学生就会取得更高的成绩。 -* 女生所占学校的比例(`female_per`) 与SAT成绩呈正相关,而男生所占学生比例(`male_per`)成负相关。 -* 没有问卷与SAT成绩成正相关。 -* SAT成绩由明显的种族不平等(`white_per`, `asian_per`, `black_per`, `hispanic_per`)。 -* `ell_percent` 与SAT成绩明显负相关。 +* `total_enrollment` 与 `sat_score` 强相关,这是令人惊讶的,因为你曾经认为越小的学校越专注于学生就会取得更高的成绩。 +* 女生所占学校的比例(`female_per`) 与 SAT 成绩呈正相关,而男生所占学生比例(`male_per`)成负相关。 +* 没有问卷与 SAT 成绩成正相关。 +* SAT 成绩有明显的种族不平等(`white_per`、`asian_per`、`black_per`、`hispanic_per`)。 +* `ell_percent` 与 SAT 成绩明显负相关。 -每一个条目都是一个潜在的角度来挖掘和讲述一个关于数据的故事。 +每一个条目都是一个挖掘和讲述数据故事的潜在角度。 ### 设置上下文 -在我们开始数据挖掘之前,我们将希望设置上下文,不仅为了我们自己,也是为了其它阅读我们分析的人。一个好的方法就是建立挖掘图标或者地图。因此,我们将在地图标出所有学校的位置,这将有助于读者理解我们所探索的问题。 +在我们开始数据挖掘之前,我们将希望设置上下文,不仅为了我们自己,也是为了其它阅读我们分析的人。一个好的方法就是建立挖掘图表或者地图。因此,我们将在地图标出所有学校的位置,这将有助于读者理解我们所探索的问题。 在下面的代码中,我们将会: * 建立纽约市为中心的地图。 -* 为城市里的每所高中添加一个标号。 +* 为城市里的每所高中添加一个标记。 * 显示地图。 -In [82]: +In \[82]: + ``` import folium from folium import plugins @@ -1067,45 +1051,49 @@ for name, row in full.iterrows(): folium.Marker([row["lat"], row["lon"]], popup="{0}: {1}".format(row["DBN"], row["school_name"])).add_to(marker_cluster) schools_map.create_map('schools.html') schools_map - ``` -Out[82]:![](https://www.dataquest.io/blog/images/storytelling/map.png) +Out\[82]: -这个地图十分有用,但是不容易查看纽约哪里学校最多。因此,我们将用热图来代替它: +![](https://www.dataquest.io/blog/images/storytelling/map.png) + +这个地图十分有用,但是不容易查看纽约哪里学校最多。因此,我们将用热力图来代替它: + +In \[84]: -In [84]: ``` schools_heatmap = folium.Map(location=[full['lat'].mean(), full['lon'].mean()], zoom_start=10) schools_heatmap.add_children(plugins.HeatMap([[row["lat"], row["lon"]] for name, row in full.iterrows()])) schools_heatmap.save("heatmap.html") schools_heatmap - ``` -Out[84]:![](https://www.dataquest.io/blog/images/storytelling/heatmap.png) +Out\[84]: + +![](https://www.dataquest.io/blog/images/storytelling/heatmap.png) ### 区域级别映射 -热图能够很好的标出梯度,但是我们将需要更结构化的画出不同城市之间的SAT分数差距。学校地区是一个很好的方式图形化信息,就像每个区域都有自己的管理者。纽约市数十个学校区域,并且每个区域都是一个小的地理区域。 +热力图能够很好的标出梯度,但是我们将需要更结构化的画出不同城市之间的 SAT 分数差距。学区是一个图形化这个信息的很好的方式,就像每个区域都有自己的管理者。纽约市有数十个学区,并且每个区域都是一个小的地理区域。 -我们可以通过学校区域来计算SAT分数,然后将它们画在地图上。在下面的代码中,我们将会: +我们可以通过学区来计算 SAT 分数,然后将它们画在地图上。在下面的代码中,我们将会: -* 通过学校区域对`full`进行分组。 -* 计算每个学校区域的每列的平均值。 -* 去掉`school_dist`头部的0,然后我们就可以匹配地理数据了。 +* 通过学区对 `full` 进行分组。 +* 计算每个学区的每列的平均值。 +* 去掉 `school_dist` 字段头部的 0,然后我们就可以匹配地理数据了。 + +In \[ ]: -In [ ]: ``` district_data = full.groupby("school_dist").agg(np.mean) district_data.reset_index(inplace=True) district_data["school_dist"] = district_data["school_dist"].apply(lambda x: str(int(x))) - ``` -我们现在将可以画出SAT在每个学校区域的平均值了。因此,我们将会读取[GeoJSON][22]中的数据,转化为每个区域的形状,然后通过`school_dist`列对每个区域图形和SAT成绩进行匹配。最终我们将创建一个图形: +我们现在将可以画出 SAT 在每个学区的平均值了。因此,我们将会读取 [GeoJSON][22] 中的数据,转化为每个区域的形状,然后通过 `school_dist` 列对每个区域图形和 SAT 成绩进行匹配。最终我们将创建一个图形: + +In \[85]: -In [85]: ``` def show_district_map(col): geo_path = 'schools/districts.geojson' @@ -1123,18 +1111,20 @@ def show_district_map(col): return districts show_district_map("sat_score") - ``` -Out[85]:![](https://www.dataquest.io/blog/images/storytelling/district_sat.png) +Out\[85]: -### 挖掘注册人数与SAT分数 +![](https://www.dataquest.io/blog/images/storytelling/district_sat.png) -现在我们已经依地区画出学校位置和STA成绩确定了上下文,浏览我们分析的人将会对数据的上下文有更好的理解。现在我们已经完成了基础工作,我们可以开始从我们上面寻找关联时所提到的角度分析了。第一个分析角度是学校注册学生人数与SAT成绩。 +### 挖掘注册学生数与SAT分数 -我们可以通过所有学校的注册学生与SAT成绩的散点图来分析。 +现在我们已经依地区画出学校位置和 SAT 成绩确定了上下文,浏览我们分析的人将会对数据的上下文有更好的理解。现在我们已经完成了基础工作,我们可以开始从我们上面寻找关联时所提到的角度分析了。第一个分析角度是学校注册学生人数与 SAT 成绩。 + +我们可以通过所有学校的注册学生与 SAT 成绩的散点图来分析。 + +In \[87]: -In [87]: ``` %matplotlib inline @@ -1142,24 +1132,25 @@ full.plot.scatter(x='total_enrollment', y='sat_score') ``` -Out[87]: +Out\[87]: + ``` ``` ![](data:image/png;base64,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) -如你所见,底部左边低注册人数低SAT成绩有一个集群。这个集群意外,SAT成绩与全部注册人数只有轻微正相关。画出的关联显示了意想不到的图形. +如你所见,底下角注册人数较低的部分有个较低 SAT 成绩的聚集。这个集群以外,SAT 成绩与全部注册人数只有轻微正相关。这个画出的关联显示了意想不到的图形. 我们可以通过获取低注册人数且低SAT成绩的学校的名字进行进一步的分析。 -In [88]: +In \[88]: + ``` full[(full["total_enrollment"] < 1000) & (full["sat_score"] < 1000)]["School Name"] - ``` -Out[88]: +Out\[88]: ``` 34 INTERNATIONAL SCHOOL FOR LIBERAL ARTS 143 NaN @@ -1176,129 +1167,134 @@ Out[88]: Name: School Name, dtype: object ``` -在Google上进行了一些搜索确定了这些学校大多数是为了正在学习英语而开设的,所以由这低注册人数。这个挖掘向我们展示了并不是所有的注册人数都与SAT成绩有关联 - 这里是否由学习英语作为第二语言的学生。 +在 Google 上进行了一些搜索确定了这些学校大多数是为了正在学习英语而开设的,所以有这么低注册人数(规模)。这个挖掘向我们展示了并不是所有的注册人数都与 SAT 成绩有关联 - 而是与是否将英语作为第二语言学习的学生有关。 -### 挖掘英语学习者和SAT成绩 +### 挖掘英语学习者和 SAT 成绩 -现在我们知道英语学习者所占学校学生比例与低的SAT成绩有关联,我们可以探索其中的规律。`ell_percent`列表示一个学校英语学习者所占的比例。我们可以制作关于这个关联的散点图。 +现在我们知道英语学习者所占学校学生比例与低的 SAT 成绩有关联,我们可以探索其中的规律。`ell_percent` 列表示一个学校英语学习者所占的比例。我们可以制作关于这个关联的散点图。 + +In \[89]: -In [89]: ``` full.plot.scatter(x='ell_percent', y='sat_score') - ``` -Out[89]: +Out\[89]: + ``` ``` ![](data:image/png;base64,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) -看起来这里有一组学校有着高的`ell_percentage`值并且有这低的SAT成绩。我们可以在区域层面调查这个关系,通过找出每个区域英语学习者所占的比例,并且查看是否与我们的区域层面SAT地图所匹配: +看起来这里有一组学校有着高的 `ell_percentage` 值并且有着低的 SAT 成绩。我们可以在学区层面调查这个关系,通过找出每个学区英语学习者所占的比例,并且查看是否与我们的学区层面的 SAT 地图所匹配: + +In \[90]: -In [90]: ``` show_district_map("ell_percent") - ``` -Out[90]: +Out\[90]: ![](https://www.dataquest.io/blog/images/storytelling/district_ell.png) -我们一可通过两个区域层面地图来查看,一个低ELL(English-language)学习者比例的地区更倾向有高SAT成绩,反之亦然。 +我们可通过两个区域层面地图来查看,一个低 ELL(English-language)学习者比例的地区更倾向有高 SAT 成绩,反之亦然。 -### 关联问卷分数和SAT分数 +### 关联问卷分数和 SAT 分数 -学生、家长和老师的问卷结果如果与SAT分数有很大的关联的假设是合理的。就使例如具有高学术期望的学校倾向于有着更高的SAT分数是合理的。为了测这个理论,让我们画出SAT分数和多种问卷指标: +学生、家长和老师的问卷结果如果与 SAT 分数有很大的关联的假设是合理的。就例如具有高学术期望的学校倾向于有着更高的 SAT 分数是合理的。为了测这个理论,让我们画出 SAT 分数和多种问卷指标: + +In \[91]: -In [91]: ``` full.corr()["sat_score"][["rr_s", "rr_t", "rr_p", "N_s", "N_t", "N_p", "saf_tot_11", "com_tot_11", "aca_tot_11", "eng_tot_11"]].plot.bar() - ``` -Out[91]: +Out\[91]: + ``` ``` ![](data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAX4AAAEuCAYAAACJVHkLAAAABHNCSVQICAgIfAhkiAAAAAlwSFlzAAALEgAACxIB0t1+/AAAGXtJREFUeJzt3XuUZWV95vHvYxPGG6CdICh2xBgYhTGKzgBRZ9KJtw5mxJgBJIkxxKgrs1AZzSzUOIKXGJNBExXHRRQRr4wOXnAFBWLSjkYU0PYOCpp2ASoSb1wMI+pv/ti75FBUVRd96uyzu97vZ61aVft23l9Xdz97n/fs992pKiRJ7bjDvAuQJA3L4Jekxhj8ktQYg1+SGmPwS1JjDH5JaszUwZ9kS5LLklye5MQltt8/yYVJbkry3EXbtif5XJJtSS6athZJ0o7tNs3BSTYApwKPAq4GLk5yTlVdOrHbd4BnAk9Y4iUK2FxV352mDknS6k17xX8ocEVVba+qm4GzgCMnd6iqa6vqEuDmZV4jU9YgSbodpg3+/YArJ5av6tetVgF/n+SSJE+bshZJ0ipM1dVDF9zTeHhVfTPJ3sAFSS6rqo9O7pDEOSUkaSdU1ZI9KtNe8V8NbJpY3kR31b/aor7Zf78WeC9d19FS+2WaL+DF077GeqhhLHWMoYax1DGGGsZSxxhqGEsda1HDStk7bfBfAhyQZP8kuwPHAOcss++tCkly5yR79D/fBXgM8Pkp65Ek7cBUXT1V9eMkxwPnARuA06vq0iTP6LeflmRf4GJgT+CnSZ4NHATcA3hPkoU63l5V509TjyRpx6bt46eqPgh8cNG60yZ+/ha37g5acAPw4GnbX6WtA7Wzkq3zLqC3dd4FMI4aYBx1bJ13Ab2t8y6AcdQA46hj6yxfPDXy+fiT1I76qyRJt7ZSdjplgyQ1xuCXpMYY/JLUmKk/3JUWW6tBd362I82Gwa8ZmTb710fmexLUGBn80sx5EtS42McvSY0x+CWpMQa/JDXG4Jekxhj8ktQYg1+SGmPwS1JjDH5JaozBL0mNceSutM45bYQWM/ilJjhthG5hV48kNcbgl6TGGPyS1BiDX5IaY/BLUmMMfklqjMEvSY0x+CWpMQa/JDXG4Jekxhj8ktQYg1+SGmPwS1JjDH5JaozBL0mNMfglqTEGvyQ1xuCXpMZMHfxJtiS5LMnlSU5cYvv9k1yY5KYkz709x0qS1t5UwZ9kA3AqsAU4CDg2yQMW7fYd4JnAKTtxrCRpjU17xX8ocEVVba+qm4GzgCMnd6iqa6vqEuDm23usJGntTRv8+wFXTixf1a+b9bGSpJ2025TH1xDHJjl5YnFrVW2dol1JWneSbAY2r2bfaYP/amDTxPImuiv3NT22qk7emeIkqRX9BfHWheUkJy2377RdPZcAByTZP8nuwDHAOcvsmymOlSStkamu+Kvqx0mOB84DNgCnV9WlSZ7Rbz8tyb7AxcCewE+TPBs4qKpuWOrYaeqRJO1Yqqbppp+9JFVVi98taMSS1HQf/wCE9fD3PobfxRhq0PBWyk5H7kpSYwx+SWqMwS9JjTH4JakxBr8kNcbgl6TGGPyS1BiDX5IaY/BLUmOmnaRt7rpRidNzVKKkVuzywd+Zfji6JLXCrh5JaozBL0mNMfglqTEGvyQ1xuCXpMYY/JLUGINfkhpj8EtSYwx+SWrMOhm5K0k75hQvHYNfUmOc4sWuHklqjMEvSY0x+CWpMQa/JDXG4Jekxhj8ktQYg1+SGmPwS1JjDH5JaozBL0mNMfglqTEGvyQ1xuCXpMZMHfxJtiS5LMnlSU5cZp/X9Ns/m+SQifXbk3wuybYkF01biyRpx6aaljnJBuBU4FHA1cDFSc6pqksn9jkC+OWqOiDJYcDrgcP7zQVsrqrvTlOHJGn1pr3iPxS4oqq2V9XNwFnAkYv2eTxwJkBVfRK4W5J9Jrbv+pNbS9IuZNrg3w+4cmL5qn7davcp4O+TXJLkaVPWIklahWmfwLXaR9ksd1X/iKr6RpK9gQuSXFZVH52yJkkatXk/AnLa4L8a2DSxvInuin6lfe7dr6OqvtF/vzbJe+m6jm4T/ElOnljcWlVbp6xbkuZsbR8BmWQzsHlVR1btfONJdgO+DDwS+AZwEXDsEh/uHl9VRyQ5HPibqjo8yZ2BDVV1fZK7AOcDL66q8xe1USud1boz5/S/wF394clj4t/JLcbwuxhDDWMxlt/FEHWslJ1TXfFX1Y+THA+cB2wATq+qS5M8o99+WlWdm+SIJFcANwLH9YfvC7wnyUIdb18c+pKktTfVFf8QvOLf9fh3cosx/C7GUMNYjOV3Me8rfkfuSlJjDH5Jasy0d/VI0qrM+xZG3cLglzSgtb2FUTvHrh5JaozBL0mNMfglqTEGvyQ1xuCXpMYY/JLUGG/nXEe8T1rSahj86473SUtamV09ktQYg1+SGmPwS1JjDH5JaozBL0mNMfglqTEGvyQ1xuCXpMYY/JLUGINfkhpj8EtSYwx+SWqMwS9JjTH4JakxBr8kNcbgl6TGGPyS1BiDX5IaY/BLUmMMfklqjA9b17qUZNqnzgNQVT59XuuOwa91bNrsN/O1PtnVI0mNMfglqTFTB3+SLUkuS3J5khOX2ec1/fbPJjnk9hwrSVpbUwV/kg3AqcAW4CDg2CQPWLTPEcAvV9UBwNOB16/2WEnS2pv2iv9Q4Iqq2l5VNwNnAUcu2ufxwJkAVfVJ4G5J9l3lsZKkNTZt8O8HXDmxfFW/bjX73GsVx0qS1ti0t3Ou9n65qe6LS3LyxOLWqtq6hi+/JsZz3/j8fxedMdQxhhpgHHWMoQYYRx1jqAHWuo4km4HNq9l32uC/Gtg0sbyJ7sp9pX3u3e/zc6s4FoCqOnm5AsY1wGa+942P5XcxhjrGUAOMo44x1ADjqGMMNcBs6ugviLcuLCc5abl9p+3quQQ4IMn+SXYHjgHOWbTPOcAf9IUcDny/qq5Z5bGSpDU21RV/Vf04yfHAecAG4PSqujTJM/rtp1XVuUmOSHIFcCNw3ErHTlOPJGnHUrUmXdMzk6TG8vZsJV0f//RdPbvCn1XS+K2UnY7claTGGPyS1BiDX5IaY/BLUmMMfklqjMEvSY0x+CWpMQa/JDXG4Jekxhj8ktQYg1+SGmPwS1JjDH5JaozBL0mNMfglqTEGvyQ1xuCXpMYY/JLUGINfkhpj8EtSYwx+SWqMwS9JjTH4JakxBr8kNcbgl6TGGPyS1BiDX5IaY/BLUmMMfklqjMEvSY0x+CWpMQa/JDXG4Jekxhj8ktQYg1+SGmPwS1Jjdjr4k2xMckGSryQ5P8ndltlvS5LLklye5MSJ9ScnuSrJtv5ry87WIklavWmu+J8HXFBVBwIf7pdvJckG4FRgC3AQcGySB/SbC3hVVR3Sf31oilokSas0TfA/Hjiz//lM4AlL7HMocEVVba+qm4GzgCMntmeK9iVJO2Ga4N+nqq7pf74G2GeJffYDrpxYvqpft+CZST6b5PTluookSWtrt5U2JrkA2HeJTX82uVBVlaSW2G+pdQteD7yk//mlwCuBpy5Tx8kTi1urausKrytJzUmyGdi8mn1XDP6qevQKjVyTZN+q+laSewLfXmK3q4FNE8ub6K76qaqf7Z/kjcAHVqjj5JXqlKTW9RfEWxeWk5y03L7TdPWcAzyl//kpwPuW2OcS4IAk+yfZHTimP47+ZLHgt4HPT1GLJGmVUrVSb8wKByYbgXcBvwhsB46uqu8nuRfwhqp6XL/fbwJ/A2wATq+qv+jXvwV4MF130D8Dz5j4zGCynaqq0X8I3HV17dzvcuJV2BX+rJLGb6Xs3OngH4rBL0m330rZ6chdSWqMwS9JjTH4JakxBr8kNcbgl6TGGPyS1BiDX5IaY/BLUmMMfklqzIqTtOn2ctCtpPEz+NeIUy1I2lXY1SNJjTH4JakxBr8kNcbgl6TGGPyS1BiDX5IaY/BLUmMMfklqjMEvSY0x+CWpMQa/JDXG4Jekxhj8ktQYg1+SGmPwS1JjDH5JaozBL0mNMfglqTEGvyQ1xuCXpMYY/JLUGINfkhpj8EtSYwx+SWrMTgd/ko1JLkjylSTnJ7nbMvu9Kck1ST6/M8dLktbWNFf8zwMuqKoDgQ/3y0s5A9gyxfFTS7J5Vq+9K9UA46hjDDXAOOoYQw0wjjrGUAOMo45Z1zBN8D8eOLP/+UzgCUvtVFUfBb63s8evkc0zfO3V2jzvAnqb510A46gBxlHH5nkX0Ns87wIYRw0wjjo2z/LFpwn+farqmv7na4B9Bj5ekrQTdltpY5ILgH2X2PRnkwtVVUlqZ4uY9nhJ0uqlaufyNsllwOaq+laSewL/WFX3X2bf/YEPVNUDb+/xnhAkaedUVZZav+IV/w6cAzwF+Mv++/tmcfxyhUuSds40V/wbgXcBvwhsB46uqu8nuRfwhqp6XL/fO4FfA34e+Dbwoqo6Y7njp/vjSJJ2ZKeDX5K0a3LkriQ1Zt0Ff5ITkuyVzulJtiV57BzqeOtq1s24hl9I8tr+d/DpJK9O8vND1rBMXRuT/Moc2v2l1awbqJbdkzwoyQOT7D6PGhZL8qJ51zAWSR497xoAkhw3i9ddd8EP/FFV/QB4DLAReDLwijnU8e8mF5LsBjx04BrOovtc5YnAfwGuBf73wDUAkOQjSfbsP9v5FPDGJH89cBlnL7Hu3QPXQJLHAV8FXgOcCnw1yRFD17GEp827AIAkfzvvGoA3zbuA3ktm8aLT3NUzVgt3AT0OeGtVfSEZ7sagJC8Ang/cKcn1E5tuBob+B71vVb10YvllSY4ZuIYFe1XVdUn+GHhLVZ20eP6mWUnyAOAgYK8kT6T7N1LAnsAdh6hhkVcBv15VV/T13Q84t/+aqUX/Jhe706zbn6hj43Kb6P7vDlHDB1bYPNg74x38P7jHLNpcj8H/qSTnA78EPC/JnsBPh2q8ql4OvDzJK6pq2fmHkhxcVV+ccTnnJzmWW67yjwLOn3Gby9nQj9c4Gnhhv26oOwsOBP4zsFf/fcH1zOcq97qF0O99DbhuoLa/BxxaVd9avCHJlQPVAPAvwNeX2bb3QDU8gq5H4IaJdUV38jlsoBqgC/ctLD21zcdn0eB6DP6nAg8GvlpVP+z7tH/WTzZQ4LJS6PfeBhwy4zKeDpwALHy2cAfgxiRPpxswveeM25/0EuA84J+q6qL+KvfyIRquqvcD70/ysKpa9j9SkudX1V8MUNKnkpxLdzszdCfkS/p3I1TVe2bY9lvpbqG+TfAD75xhu4t9DXhkVd0m/Ac8AX0S+GFVbV2ihi8PVAPA3wF3raptS9TxkVk02NztnEm2VdWsA3eXqGOok+BqDBi6K9UwyN9Jkjdz63c7mVyuqpl8oDcmSY4HPlZVn1li27Oq6jVzKKsZBn/DdYyhhgVjqGUMNfR1zOUkmOT+VXXZ0O1qeUnuWlU37HjP22c93tUj7eqOnlO7F8yp3VsZw62UQ914sApfmsWLrsc+/rlLdxvRvatqpb7K/zdUPdKCJK9dYfNYnoL3JmDTrBtJ8jtLrF74cPees25/oo7nrrB5j1m0ua6Cf2SB+0EW3cs/qaoOH6gOrd7g9/TPwR8Cf0r3/2Dx5wy/O1QRI7mV8izgHdz2rr8w7G2+fw6cQnfL9+I6ZtIrs66Cvzf3wO2fL/CpJIdW1UWzbm8pIzsJrsbMQjfJSctsKoCqekn//eWzqmFELgG+UFX/tHhDkpMHrGMMt1J+Hjilqm7TrZPkkQPVALANeF9VXbJEHU+dRYPrKvjHELgASe4A/Efg95N8HbhxosQhpyqY+0lwJKF7I7cdM3AXult/f4EZjY6cwizfefwOcNNSG6pq/xm2u9gYbqU8geXHTzxxoBqgu938O8ts+w+zaHBd3dXTB+4VwH3oBofMJXD7q+3rgYO5ZSTxQiHbB6zjTOB1cz4J/ikrhG5V3WXgevYEntW3/y7glVX17YHaXtVJcAySnF1VS/WBN2cMtxr3dby2qp65Fq+1rq746f4D3YNu1O7cHuDSv/M4m+65wvPq6hnFu46qOmWipoXQPY6uf/WVQ9XRD+T7b8DvAW8BHlJVS42UnKVd6Z3HXCavWyzJhVX1q3Mu42hg7sFP1z22JtZV8I8hcCccznxDdxQnQZh/6CY5BfhturmSfqWqVpqvZmbGchLcxcxjLqV1b10Ff2/egbtg8KmgJ43lJDiS0H0O8CO6OYJeuGjSvkGnrpj3SVCC9Rn8cw3cBUP25a9gDCfBuYduVY1ioOJIToLS+vpwV7eWZP+l1o/kpNScJD+lOwkuvl8bhn/n8eyqevVy65I8tqrOG6qe5QwxjUaSR1TVx5Zbl+QFQ9zqm+Soqnr3cuuS/GFVvXlN2jL4pfYsFahJPlNVDx64jr+sqhOXW5fkgUvdZ7/GNSz1uxh83qYh61iPXT2SltE/n+F3gfsuGj27B8vfSz5LjwFOXLTuiIV1swz9JL8KPAzYO8lzuOUmiD0YcB6zJL9J92feL8lrFtWx1LvDqRn8Uls+DnyT7mEnp0ysvwH47FBFJPkT4L8C91s0IdoewG1GFc/I7n17G7j1nDjX0T2qdCjfoHsc6ZH99wXX090IsObs6pEalWRfupGhBVw01EC2vu29gLvTPQ978or/hqoa9J1Hkv2ranuSPQDm9aF7kp+je6dxYL/qsqqayRX/KO52kDSsJEfTTZtwFN0ApYuSHDVU+1X1g6raXlVPojsBPJ7usZj3HqqGCXsk2QZ8EfhiP+3LslOdzNDDga8Ar+u/Lk/ya7NoyCt+qUFJPgc8auEqP8newIeHHu+S5Nl0zz1+D13f9hOANwz5BK4kFwIvqKp/7Jc3Ay+vqocNVUPf7qeBY6vqy/3ygcBZVfWQtW7LPn6pTQGunVj+DvMZ4f3HwGFVdSNAklcAnwCGfPTinRdCH6CqtiYZdA6p3m4Lod/X8ZUkM8log19q04eA85K8gy7wj6GbzXUefrrMz0P55yT/g+5B9KEbVf21OdTxqSRvBN42UcdtpmpeC3b1SI3qn0D18H7xo1X13jnU8By6h8NMdvW8uar+esAaNgIvZuJ3AZw89FQaSf4NcPyiOv5XVa35czMMfqlBOxo4NXAtD6WbebLoTkDbBm5/xRGzA9ax4mjqNW3L4Jfas8wo0c9X1QMHruOtVfXkHa2bcQ1jHrk7k9HU9vFLDRnJwKlJt7ptsv8w86FDNDyPEbPL1DH4aGqDX2rLO+g+xF0YOLUQdtdPDpxKsrGqvjurIpK8AHg+cKckkwOmbqabvXQIi0fMhq67aWYjZpexeDT1wt/JdcDnZtGgXT2SbmOoro4kr6iq562w/eCq+uKMa9i9qn60wvZRPIZyLZ9G5shdSXOzUuj33jZADcuGfm8Uj6FkDZ9GZvBLUmMMfklqjMEvNSTJfeddg+bP4Jfa8n8AkvzDDvZ71AC1rMaaj1rdCTv6HGIof7BWL+RdPVJDknwGeDfwJ8CruPXEbFVVr5pDTQ8C9ueW28urqt4zYPsHAi8HDuaWD1Crqgb9UHfRba0LfgBcDDy3qtZs/iDv45fa8iS6+XAWP3Vq4R72QSU5A3gg3Vz4kxO0DRb8wBnASXQnwi3AcXS/n6G9GrgSeGe//CTgfsA24E3A5rVqyCt+qUFJjqiqc0dQx5eAg2uOQZTk01X1kMkpKxbWDVzH5xY/D2FhyoYkn62qB61VW17xSw2qqnOT/BZwEHAn+qv9qnrJwKVc3Ncw00FaO3BTkg3AFUmOpxvRO4/5+H+Y5Bi6rjjonvt7U//zmp4YveKXGpTkNLrA/w3gDXSPYPxkVT114Do2A+cA3+KWD3JryCeBJTkUuBS4G/BSYE/gr6rqE0PV0NdxP7runsP7VZ8ATgCuBh5aVR9bs7YMfqk9C90aC90LSe4KfKiqHjFwHV+lmxfnC0z08VfV9iHraI1dPVKb/rX//sMk+9HNArnvHOr4dlWdM4d2fybJBcBRVfX9fvnudM+6fezAddyD7vnD+3PrO5z+aK3bMvilNn2gD7j/STczZQFvnEMd2/rHP34AWJgzZ9DbOYG9F0K/b/x7SfYZsP0F7wf+L3ABt7z7mUmXjMEvtenLwE+q6uwkBwOHAIM/ehG4M13gP2bR+iGD/ydJ7lNVXwdIsj/zefbvnYZ6App9/FKDJvr4HwG8jO7K/0VVddicSxtcki10zwD4CN14hv8EPL2qPjRwHS8DLqyqv5t1W07ZILXpJ/333wLe0IfN7kMXkWRTkvcmubb/OjvJvYesoQ/4f0/3Lugs4DnAD4esoXcCXRfcTUmu77+um0VDdvVIbbo6yd8CjwZekeSOzOdC8Azg7cDR/fLv9esePVQBSZ4GPAvYRDdK9nDgQrpbXYe0F92f/75V9eIk92FGH7h7xS+16WjgPOAx/Qebdwf++xzq2Luqzqiqm/uvNwP3GLiGZwOHAtur6tfpPu/4wcA1ALwOOIxuqgboHgF56iwa8opfalBV3QicPbH8Tbrnvg7tO0meTPcs4NCF3r8MXMNNVfWvSUhyx6q6LMm/HbgGgMOq6pAk2wCq6rtJZtL9ZvBLmqfj6K5qF2YF/Xi/bkhX9re2vg+4IMn3gO0D1wDwo37qCACS7M2M7i7yrh5Jc5PkTOCEqvpev7wROGUWg5ZWWc9muikbPrSKZ/Guddu/T9cF91DgTLq5el5YVe9a87YMfknzsjD75I7WtSLJA4BH9osfrqpLZ9GOXT2S5ilJNlbVd/uFjcxnLvxR6IN+JmE/yeCXNE+vBC5M8i66D3ePAv58viWtf3b1SJqrfsqI36Cbl+YfqupLcy5p3TP4JakxDuCSpMYY/JLUGINfkhpj8EtSY/4/UzeqepUNQsYAAAAASUVORK5CYII=) -惊人的,关联最大的两个事实是`N_p`和`N_s`,分别是家长和学生回应的问卷。都与注册人数有着很强的关联,所以很可能偏离了`ell_learner`。此外指标关联最强的就是`saf_t_11`。就是学生、家长和老师对学校安全程度的感知。这说明了,越安全的学校,更能让学生在环境里安心学习。然而其它因子,像互动,交流和学术水平都与SAT分数无关,这也许表明了纽约在问卷中问了不理想的问题或者想错了因子(如果他们的目的是提高SAT分数的话)。 +惊人的是,关联最大的两个因子是 `N_p` 和 `N_s`,它们分别是家长和学生回应的问卷。都与注册人数有着强关联,所以很可能偏离了 `ell_learner`。此外指标关联最强的就是 `saf_t_11`,这是学生、家长和老师对学校安全程度的感知。这说明了,越安全的学校,更能让学生在环境里安心学习。然而其它因子,像互动、交流和学术水平都与 SAT 分数无关,这也许表明了纽约在问卷中问了不理想的问题或者想错了因子(如果他们的目的是提高 SAT 分数的话)。 -### 挖掘种族和SAT分数 +### 挖掘种族和 SAT 分数 -其中一个就读就是调查种族和SAT分数的联系。这是一个大相关微分,并且将其画出来帮助我们理解到底发生了什么: +其中一个角度就是调查种族和 SAT 分数的联系。这是一个大相关微分,将其画出来帮助我们理解到底发生了什么: + +In \[92]: -In [92]: ``` full.corr()["sat_score"][["white_per", "asian_per", "black_per", "hispanic_per"]].plot.bar() - ``` -Out[92]: +Out\[92]: + ``` ``` ![](data:image/png;base64,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) -看起来更高的白种和亚洲学生与更高的SAT分数有关联,但是更高的黑人和西班牙裔与更低的SAT分数有关联。对于西班牙学生,这可能因为近年的移民还是英语学习者的事实。我们可以标出区层面的西班牙裔的比例并观察联系。 +看起来更高比例的白种和亚洲学生与更高的 SAT 分数有关联,而更高比例的黑人和西班牙裔与更低的 SAT 分数有关联。对于西班牙学生,这可能因为近年的移民还是英语学习者的事实。我们可以标出学区层面的西班牙裔的比例并观察联系。 -In [93]: +In \[93]: ``` show_district_map("hispanic_per") - ``` -Out[93]: +Out\[93]: ![](https://www.dataquest.io/blog/images/storytelling/district_hispanic.png) -看起来这里与英语学习者比例有关联,但是这将有必要做一些挖掘这种和在SAT分数上的其它种族差异。 +看起来这里与英语学习者比例有关联,但是有必要对这种和其它种族在 SAT 分数上的差异进行挖掘。 -### SAT分数上的性别差异` +### SAT 分数上的性别差异 -挖掘性别与SAT分数之间的关系是最后一个角度。我们注意学校更高的女生比例倾向于与更高的SAT分数有关联。我们可以可视化为一个条形图: +挖掘性别与 SAT 分数之间的关系是最后一个角度。我们注意更高的女生比例的学校倾向于与更高的 SAT 分数有关联。我们可以可视化为一个条形图: + +In \[94]: -In [94]: ``` full.corr()["sat_score"][["male_per", "female_per"]].plot.bar() - ``` -Out[94]: +Out\[94]: + ``` ``` ![](data:image/png;base64,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) -为了在关联中挖掘更多,我们可以制作一个`female_per`和`sat_score`的散点图: +为了挖掘更多的关联性,我们可以制作一个 `female_per` 和 `sat_score` 的散点图: + +In \[95]: -In [95]: ``` full.plot.scatter(x='female_per', y='sat_score') - ``` -Out[95]: +Out\[95]: + ``` ``` ![](data:image/png;base64,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) -看起来这里有一个高女生比例高SAT成绩的簇(右上角)。我们可以获取簇中学校的名字: +看起来这里有一个高女生比例、高 SAT 成绩的簇(右上角)(LCTT 译注:此处散点图并未有如此迹象,可能数据图有误)。我们可以获取簇中学校的名字: + +In \[96]: -In [96]: ``` full[(full["female_per"] > 65) & (full["sat_score"] > 1400)]["School Name"] - ``` -Out[96]: +Out\[96]: + ``` 3 PROFESSIONAL PERFORMING ARTS HIGH SCH 92 ELEANOR ROOSEVELT HIGH SCHOOL @@ -1310,36 +1306,34 @@ Out[96]: Name: School Name, dtype: object ``` -使用Google进行搜索可以得到这些是专注于表演艺术的精英学校。这些学校有着更高比例的女生和更高的SAT分数。这可能解释了更高的女生比例和SAT分数的关联,并且相反的更高的男生比例与更低的SAT分数。 +使用 Google 进行搜索可以知道这些是专注于表演艺术的精英学校。这些学校有着更高比例的女生和更高的 SAT 分数。这可能解释了更高的女生比例和 SAT 分数的关联,并且相反的更高的男生比例与更低的 SAT 分数。 -### AP成绩 +### AP 成绩 -至今,我们将关注人口统计角度。一个我们通过数据来看参加高阶测试的学生和SAT分数的角度。因为高学术获得者倾向于有着高的SAT分数说明了它们是有关联的。 +至今,我们关注的是人口统计角度。还有一个角度是我们通过数据来看参加高阶测试(AP)的学生和 SAT 分数。因为高学术成绩获得者倾向于有着高的 SAT 分数说明了它们是有关联的。 -In [98]: +In \[98]: ``` full["ap_avg"] = full["AP Test Takers "] / full["total_enrollment"] full.plot.scatter(x='ap_avg', y='sat_score') - ``` -Out[98]: +Out\[98]: ``` ``` ![](data:image/png;base64,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) -看起来它们之间确实有着很强的关联。有趣的是右上角高SAT分数的学校有着高的AP测试通过比例: +看起来它们之间确实有着很强的关联。有趣的是右上角高 SAT 分数的学校有着高的 AP 测试通过比例: -In [99]: +In \[99]: ``` full[(full["ap_avg"] > .3) & (full["sat_score"] > 1700)]["School Name"] - ``` -Out[99]: +Out\[99]: ``` 92 ELEANOR ROOSEVELT HIGH SCHOOL 98 STUYVESANT HIGH SCHOOL @@ -1352,42 +1346,40 @@ Out[99]: Name: School Name, dtype: object ``` -功过google搜索解释了大多数高选择性的学校你需要经过测试才能进入。这就说明了为什么这些学校会有高的AP通过人数。 +通过 google 搜索解释了那些大多是高选择性的学校,你需要经过测试才能进入。这就说明了为什么这些学校会有高的 AP 通过人数。 ### 包装故事 -在数据科学中,故事不可能真正完结。通过向其他人发布分析,你允许它们拓展并且运用你的分析到他们所感兴趣的方向。比如在本文中,这里有一些角度我们没有完成并且可以探索更加深入。 +在数据科学中,故事不可能真正完结。通过向其他人发布分析,你可以让他们拓展并且运用你的分析到他们所感兴趣的方向。比如在本文中,这里有一些角度我们没有完成,并且可以探索更加深入。 -一个最好的方式开始讲述故事就是尝试拓展或者复制别人已经完成的分析。如果你觉得采取这个方式,你被欢迎拓展这篇文章的分析并得知你的收获。如果你确实这么做了,请在下面评论,那么我就可以看到了。 +一个开始讲述故事的最好方式就是尝试拓展或者复制别人已经完成的分析。如果你觉得采取这个方式,欢迎你拓展这篇文章的分析,并看看你能发现什么。如果你确实这么做了,请在下面评论,那么我就可以看到了。 ### 下一步 -如果你做的足够多,你将很有希望对讲一个关于数据的故事和构建你的第一个数据科学组合有很好的理解。一旦你完成了你的数据科学工程,发表在[Github][21]上是一个好的想法,这样别人就能够与你一起合作。 +如果你做的足够多,你看起来已经对用数据讲故事和构建你的第一个数据科学作品集有了很好的理解。一旦你完成了你的数据科学工程,发表在 [Github][21] 上是一个好的想法,这样别人就能够与你一起合作。 -_如果你洗管这篇文章,你可能希望阅读我们‘Build a Data Science Portfolio’系列文章的其它部分:_ - -* _[如何建立一个数据科学博客][4]._ -* _[建立一个机器学习工程][3]._ -* _[将帮助你的到工作的数据科学组合的关键]._ -* _[17 你能找到其它数据科学工程数据组的地方]._ +如果你喜欢这篇文章,你可能希望阅读我们‘Build a Data Science Portfolio’系列文章的其它部分: +* [如何搭建一个数据科学博客][4] +* [建立一个机器学习工程][3] +* [构建一个将帮助你找到工作的数据科学作品集的关键][2] +* [17 个你能找到其它数据科学工程数据集的地方][1] +* [怎样在 GitHub 上展示你的数据科学作品集][36] -------------------------------------------------------------------------------- via: https://www.dataquest.io/blog/data-science-portfolio-project/ -作者:[Vik Paruchuri ][a] - -译者:[Yoo-4x] - -校对:[校对者ID](https://github.com/校对者ID) +作者:[Vik Paruchuri][a] +译者:[Yoo-4x](https://github.com/Yoo-4x) +校对:[wxy](https://github.com/wxy) 本文由 [LCTT](https://github.com/LCTT/TranslateProject) 原创编译,[Linux中国](https://linux.cn/) 荣誉推出 [a]: http://twitter.com/vikparuchuri [1]:https://www.dataquest.io/blog/free-datasets-for-projects [2]:https://www.dataquest.io/blog/build-a-data-science-portfolio/ -[3]:https://www.dataquest.io/blog/data-science-portfolio-machine-learning/ +[3]:https://linux.cn/article-7907-1.html [4]:https://www.dataquest.io/blog/how-to-setup-a-data-science-blog/ [5]:https://www.dataquest.io/ [6]:http://pandas.pydata.org/pandas-docs/stable/generated/pandas.concat.html @@ -1401,7 +1393,7 @@ via: https://www.dataquest.io/blog/data-science-portfolio-project/ [14]:https://data.cityofnewyork.us/Education/NYS-Math-Test-Results-By-Grade-2006-2011-School-Le/jufi-gzgp [15]:https://data.cityofnewyork.us/Education/School-Attendance-and-Enrollment-Statistics-by-Dis/7z8d-msnt [16]:https://data.cityofnewyork.us/Education/SAT-Results/f9bf-2cp4 -[17]:http://rs.io/100-interesting-data-sets-for-statistics/ +[17]:https://www.dataquest.io/blog/free-datasets-for-projects/ [18]:https://github.com/caesar0301/awesome-public-datasets [19]:https://reddit.com/r/datasets [20]:https://www.data.gov/ @@ -1420,3 +1412,4 @@ via: https://www.dataquest.io/blog/data-science-portfolio-project/ [33]:https://www.dataquest.io/blog/python-data-science/ [34]:http://www.jupyter.org/ [35]:https://www.dataquest.io/blog/data-science-portfolio-project/#email-signup +[36]:https://www.dataquest.io/blog/how-to-share-data-science-portfolio/ \ No newline at end of file diff --git a/published/201710/20160611 How To Code Like The Top Programmers At NASA — 10 Critical Rules.md b/published/201710/20160611 How To Code Like The Top Programmers At NASA — 10 Critical Rules.md new file mode 100644 index 0000000000..0b1faff319 --- /dev/null +++ b/published/201710/20160611 How To Code Like The Top Programmers At NASA — 10 Critical Rules.md @@ -0,0 +1,56 @@ +如何像 NASA 顶级程序员一样编程 —— 10 条重要原则 +=== + +[![rules of coding nasa](http://upload-images.jianshu.io/upload_images/2489863-791757ae6bd313e6.png?imageMogr2/auto-orient/strip%7CimageView2/2/w/1240)][1] + +> 引言: 你知道 NASA 顶级程序员如何编写关键任务代码么?为了确保代码更清楚、更安全、且更容易理解,NASA  的喷气推进实验室制定了 10 条编码规则。 + +NASA 的开发者是编程界最有挑战性的工作之一。他们编写代码并将开发安全的关键任务应用程序作为其主要关注点。 + +在这种情形下,遵守一些严格的编码规则是重要的。这些规则覆盖软件开发的多个方面,例如软件应该如何编码、应该使用哪些语言特性等。 + +尽管很难就一个好的编码标准达成共识,NASA 的喷气推进实验室(JPL)遵守一个[编码规则][2],其名为“十的次方:开发安全的关键代码的规则”。 + +由于 JPL 长期使用 C 语言,这个规则主要是针对于 C 程序语言编写。但是这些规则也可以很容地应用到其它的程序语言。 + +该规则由 JPL 的首席科学家 Gerard J. Holzmann 制定,这些严格的编码规则主要是聚焦于安全。 + +NASA 的 10 条编写关键任务代码的规则: + +1. 限制所有代码为极为简单的控制流结构 — 不用 `goto` 语句、`setjmp` 或 `longjmp` 结构,不用间接或直接的递归调用。 +2. 所有循环必须有一个固定的上限值。必须可以被某个检测工具静态证实,该循环不能达到预置的迭代上限值。如果该上限值不能被静态证实,那么可以认为违背该原则。 +3. 在初始化后不要使用动态内存分配。 +4. 如果一个语句一行、一个声明一行的标准格式来参考,那么函数的长度不应该比超过一张纸。通常这意味着每个函数的代码行不能超过 60。 +5. 代码中断言的密度平均低至每个函数 2 个断言。断言被用于检测那些在实际执行中不可能发生的情况。断言必须没有副作用,并应该定义为布尔测试。当一个断言失败时,应该执行一个明确的恢复动作,例如,把错误情况返回给执行该断言失败的函数调用者。对于静态工具来说,任何能被静态工具证实其永远不会失败或永远不能触发的断言违反了该规则(例如,通过增加无用的 `assert(true)` 语句是不可能满足这个规则的)。 +6. 必须在最小的范围内声明数据对象。 +7. 非 void 函数的返回值在每次函数调用时都必须检查,且在每个函数内其参数的有效性必须进行检查。 +8. 预处理器的使用仅限制于包含头文件和简单的宏定义。符号拼接、可变参数列表(省略号)和递归宏调用都是不允许的。所有的宏必须能够扩展为完整的语法单元。条件编译指令的使用通常是晦涩的,但也不总是能够避免。这意味着即使在一个大的软件开发中超过一两个条件编译指令也要有充足的理由,这超出了避免多次包含头文件的标准做法。每次在代码中这样做的时候必须有基于工具的检查器进行标记,并有充足的理由。 +9. 应该限制指针的使用。特别是不应该有超过一级的解除指针引用。解除指针引用操作不可以隐含在宏定义或类型声明中。还有,不允许使用函数指针。 +10. 从开发的第一天起,必须在编译器开启最高级别警告选项的条件下对代码进行编译。在此设置之下,代码必须零警告编译通过。代码必须利用源代码静态分析工具每天至少检查一次或更多次,且零警告通过。 + +关于这些规则,NASA 是这么评价的: + +> 这些规则就像汽车中的安全带一样,刚开始你可能感到有一点不适,但是一段时间后就会养成习惯,你会无法想象不使用它们的日子。 + +此文是否对你有帮助?不要忘了在下面的评论区写下你的反馈。 + +--- +作者简介: + +Adarsh Verma 是 Fossbytes 的共同创始人,他是一个令人尊敬的企业家,他一直对开源、技术突破和完全保持密切关注。可以通过邮件联系他 — [adarsh.verma@fossbytes.com](mailto:adarsh.verma@fossbytes.com) + +------------------ + +via: https://fossbytes.com/nasa-coding-programming-rules-critical/ + +作者:[Adarsh Verma][a] +译者:[penghuster](https://github.com/penghuster) +校对:[wxy](https://github.com/wxy) + +本文由 [LCTT](https://github.com/LCTT/TranslateProject) 原创编译,[Linux中国](https://linux.cn/) 荣誉推出 + +[a]:https://fossbytes.com/author/adarsh/ +[1]:http://fossbytes.com/wp-content/uploads/2016/06/rules-of-coding-nasa.jpg +[2]:http://pixelscommander.com/wp-content/uploads/2014/12/P10.pdf +[3]:https://fossbytes.com/wp-content/uploads/2016/12/learn-to-code-banner-ad-content-1.png +[4]:http://pixelscommander.com/wp-content/uploads/2014/12/P10.pdf diff --git a/published/20160909 Best Linux Adobe Alternatives You Need to Know.md b/published/201710/20160909 Best Linux Adobe Alternatives You Need to Know.md similarity index 100% rename from published/20160909 Best Linux Adobe Alternatives You Need to Know.md rename to published/201710/20160909 Best Linux Adobe Alternatives You Need to Know.md diff --git a/translated/tech/20161110 User Editorial Steam Machines & SteamOS after a year in the wild.md b/published/201710/20161110 User Editorial Steam Machines & SteamOS after a year in the wild.md similarity index 59% rename from translated/tech/20161110 User Editorial Steam Machines & SteamOS after a year in the wild.md rename to published/201710/20161110 User Editorial Steam Machines & SteamOS after a year in the wild.md index 9ae3a5f5af..8659e8b4d2 100644 --- a/translated/tech/20161110 User Editorial Steam Machines & SteamOS after a year in the wild.md +++ b/published/201710/20161110 User Editorial Steam Machines & SteamOS after a year in the wild.md @@ -1,59 +1,59 @@ -用户报告:Steam Machines 与 SteamOS 发布一周年记 +回顾 Steam Machines 与 SteamOS ==== -去年今日,在非常符合 Valve 风格的跳票之后大众迎来了 [Steam Machine 的发布][2]。即使是在 Linux 桌面环境对于游戏的支持大步进步的今天,Steam Machines 作为一个平台依然没有飞跃,而 SteamOS 似乎也止步不前。这些由 Valve 发起的项目究竟怎么了?这些项目为何被发起,又是如何失败的?一些改进又是否曾有机会挽救这些项目的成败? +去年今日(LCTT 译注:本文发表于 2016 年),在非常符合 Valve 风格的跳票之后,大众迎来了 [Steam Machines 的发布][2]。即使是在 Linux 桌面环境对于游戏的支持大步进步的今天,Steam Machines 作为一个平台依然没有飞跃,而 SteamOS 似乎也止步不前。这些由 Valve 发起的项目究竟怎么了?这些项目为何被发起,又是如何失败的?一些改进又是否曾有机会挽救这些项目的成败? -**行业环境** +### 行业环境 -在 2012 年 Windows 8 发布的时候,微软像 iOS 与 Android 那样,为 Windows 集成了一个应用商店。在微软试图推广对触摸体验友好的界面时,为了更好的提供 “Metro” UI 语言指导下的沉浸式触摸体验,他们同时推出了一系列叫做 “WinRT” 的 API。然而为了能够使用这套 API,应用开发者们必须把应用程序通过 Windows 应用商城发布,并且正如其他应用商城那样,微软从中抽成30%。对于 Valve 的 CEO,Gabe Newell (G胖) 而言,这种限制发布平台和抽成行为是让人无法接受的,而且他前瞻地看到了微软利用行业龙头地位来推广 Windows 商店和 Metro 应用对于 Valve 潜在的危险,正如当年微软用 IE 浏览器击垮 Netscape 浏览器一样。 +在 2012 年 Windows 8 发布的时候,微软像 iOS 与 Android 那样,为 Windows 集成了一个应用商店。在微软试图推广对触摸体验友好的界面时,为了更好的提供 “Metro” UI 语言指导下的沉浸式触摸体验,他们同时推出了一系列叫做 “WinRT” 的 API。然而为了能够使用这套 API,应用开发者们必须把应用程序通过 Windows 应用商城发布,并且正如其它应用商城那样,微软从中抽成 30%。对于 Valve 的 CEO,Gabe Newell (G 胖) 而言,这种限制发布平台和抽成行为是让人无法接受的,而且他前瞻地看到了微软利用行业龙头地位来推广 Windows 商店和 Metro 应用对于 Valve 潜在的危险,正如当年微软用 IE 浏览器击垮 Netscape 浏览器一样。 -对于 Valve 来说,运行 Windows 的 PC 的优势在于任何人都可以不受操作系统和硬件方的限制运行各种软件。当像 Windows 这样的专有平台对像 Steam 这样的第三方软件限制越来越严格时,应用开发者们自然会想要寻找一个对任何人都更开放和自由的替代品,他们很自然的会想到 Linux 。Linux 本质上只是一套内核,但你可以轻易地使用 GNU 组件,Gnnome 等软件在这套内核上开发出一个操作系统,比如 Ubuntu 就是这么来的。推行 Ubuntu 或者其他 Linux 发行版自然可以为 Valve 提供一个无拘无束的平台,以防止微软或者苹果变成 Valve 作为第三方平台之路上的的敌人,但 Linux 甚至给了 Valve 一个创造新的操作系统平台的机会。 +对于 Valve 来说,运行 Windows 的 PC 的优势在于任何人都可以不受操作系统和硬件方的限制运行各种软件。当像 Windows 这样的专有平台对像 Steam 这样的第三方软件限制越来越严格时,应用开发者们自然会想要寻找一个对任何人都更开放和自由的替代品,他们很自然的会想到 Linux 。Linux 本质上只是一套内核,但你可以轻易地使用 GNU 组件、Gnome 等软件在这套内核上开发出一个操作系统,比如 Ubuntu 就是这么来的。推行 Ubuntu 或者其他 Linux 发行版自然可以为 Valve 提供一个无拘无束的平台,以防止微软或者苹果变成 Valve 作为第三方平台之路上的的敌人,但 Linux 甚至给了 Valve 一个创造新的操作系统平台的机会。 -**概念化** +### 概念化 如果我们把 Steam Machines 叫做主机的话,Valve 当时似乎认定了主机平台是一个机会。为了迎合用户对于电视主机平台用户界面的审美期待,同时也为了让玩家更好地从稍远的距离上在电视上玩游戏,Valve 为 Steam 推出了 Big Picture 模式。Steam Machines 的核心要点是开放性;比方说所有的软件都被设计成可以脱离 Windows 工作,又比如说 Steam Machines 手柄的 CAD 图纸也被公布出来以便支持玩家二次创作。 -原初计划中,Valve 打算设计一款官方的 Steam Machine 作为旗舰机型。但最终,这些机型只在 2013 年的时候作为原型机给与了部分测试者用于测试。Valve 后来也允许像戴尔这样的 OEM 厂商们制造 Steam Machines,并且也赋予了他们定制价格和配置规格的权利。有一家叫做 “Xi3” 的公司展示了他们设计的 Steam Machine 小型机型,那款机型小到可以放在手掌上,这一新闻创造了围绕 Steam Machines 的更多热烈讨论。最终,Valve 决定不自己设计知道 Steam Machines,而全权交给 OEM 合作厂商们。 +原初计划中,Valve 打算设计一款官方的 Steam Machine 作为旗舰机型。但最终,这些机型只在 2013 年的时候作为原型机给与了部分测试者用于测试。Valve 后来也允许像戴尔这样的 OEM 厂商们制造 Steam Machines,并且也赋予了他们制定价格和配置规格的权利。有一家叫做 “Xi3” 的公司展示了他们设计的 Steam Machine 小型机型,那款机型小到可以放在手掌上,这一新闻创造了围绕 Steam Machines 的更多热烈讨论。最终,Valve 决定不自己设计制造 Steam Machines,而全权交给 OEM 合作厂商们。 -这一过程中还有很多天马行空的创意被列入考量,比如在手柄上加入生物识别技术,眼球追踪以及动作控制等。在这些最初的想法里,陀螺仪被加入了 Steam Controller 手柄,HTC Vive 的手柄也有各种动作追踪仪器;这些想法可能最初都来源于 Steam 手柄的设计过程中。手柄最初还有些更激进的设计,比如在中心放置一块可定制化并且会随着游戏内容变化的触摸屏。但最后的最后,发布会上的手柄偏向保守了许多,但也有诸如双触摸板和内置软件等黑科技。Valve 也考虑过制作面向笔记本类型硬件的 Steam Machines 和 SteamOS。这个企划最终没有任何成果,但也许 “Smach Z” 手持游戏机会是发展的方向之一。 +这一过程中还有很多天马行空的创意被列入考量,比如在手柄上加入生物识别技术、眼球追踪以及动作控制等。在这些最初的想法里,陀螺仪被加入了 Steam Controller 手柄,HTC Vive 的手柄也有各种动作追踪仪器;这些想法可能最初都来源于 Steam 手柄的设计过程中。手柄最初还有些更激进的设计,比如在中心放置一块可定制化并且会随着游戏内容变化的触摸屏。但最后的最后,发布会上的手柄偏向保守了许多,但也有诸如双触摸板和内置软件等黑科技。Valve 也考虑过制作面向笔记本类型硬件的 Steam Machines 和 SteamOS。这个企划最终没有任何成果,但也许 “Smach Z” 手持游戏机会是发展的方向之一。 -在 [2013年九月][3],Valve 对外界宣布了 Steam Machines 和 SteamOS, 并且预告会在 2014 年中发布。前述的 300 台原型机在当年 12 月被分发给了测试者们,随后次年 1 月,2000 台原型机又被分发给了开发者们。SteamOS 也在那段时间被分发给有 Linux 经验的测试者们试用。根据当时的测试反馈,Valve 最终决定把产品发布延期到 2015 年 11 月。 +在 [2013 年九月][3],Valve 对外界宣布了 Steam Machines 和 SteamOS, 并且预告会在 2014 年中发布。前述的 300 台原型机在当年 12 月分发给了测试者们,随后次年 1 月,又分发给了开发者们 2000 台原型机。SteamOS 也在那段时间分发给有 Linux 经验的测试者们试用。根据当时的测试反馈,Valve 最终决定把产品发布延期到 2015 年 11 月。 -SteamOS 的延期跳票给合作伙伴带来了问题;戴尔的 Steam Machine 由于早发售了一年结果不得不改为搭配了额外软件甚至运行着 Windows 操作系统的 Alienware Alpha。 +SteamOS 的延期跳票给合作伙伴带来了问题;戴尔的 Steam Machine 由于早发售了一年,结果不得不改为搭配了额外软件、甚至运行着 Windows 操作系统的 Alienware Alpha。 -**正式发布** +### 正式发布 在最终的正式发布会上,Valve 和 OEM 合作商们发布了 Steam Machines,同时 Valve 还推出了 Steam Controller 手柄和 Steam Link 串流游戏设备。Valve 也在线下零售行业比如 GameStop 里开辟了货架空间。在发布会前,有几家 OEM 合作商退出了与 Valve 的合作;比如 Origin PC 和 Falcon Northwest 这两家高端精品主机设计商。他们宣称 Steam 生态的性能问题和一些限制迫使他们决定弃用 SteamOS。 -Steam Machines 在发布后收到了褒贬不一的评价。另一方面 Steam Link 则普遍受到好评,很多人表示愿意在客厅电视旁为他们已有的 PC 系统购买 Steam Link, 而不是购置一台全新的 Steam Machine。Steam Controller 手柄则受到其丰富功能伴随而来的陡峭学习曲线影响,评价一败涂地。然而针对 Steam Machines 的批评则是最猛烈的。诸如 LinusTechTips 这样的评测团体 (译者:YouTube硬件界老大,个人也经常看他们节目) 注意到了主机的明显的不足,其中甚至不乏性能为题。很多厂商的 Machines 都被批评为性价比极低,特别是经过和玩家们自己组装的同配置机器或者电视主机做对比之后。SteamOS 而被批评为兼容性有问题,Bugs 太多,以及性能不及 Windows。在所有 Machines 里,戴尔的 Alienware Alpha 被评价为最有意思的一款,主要是由于品牌价值和机型外观极小的缘故。 +Steam Machines 在发布后收到了褒贬不一的评价。另一方面 Steam Link 则普遍受到好评,很多人表示愿意在客厅电视旁为他们已有的 PC 系统购买 Steam Link, 而不是购置一台全新的 Steam Machine。Steam Controller 手柄则受到其丰富功能伴随而来的陡峭学习曲线影响,评价一败涂地。然而针对 Steam Machines 的批评则是最猛烈的。诸如 LinusTechTips 这样的评测团体 (LCTT 译注:YouTube 硬件界老大,个人也经常看他们节目)注意到了主机的明显的不足,其中甚至不乏性能为题。很多厂商的 Machines 都被批评为性价比极低,特别是经过和玩家们自己组装的同配置机器或者电视主机做对比之后。SteamOS 而被批评为兼容性有问题,Bug 太多,以及性能不及 Windows。在所有 Machines 里,戴尔的 Alienware Alpha 被评价为最有意思的一款,主要是由于品牌价值和机型外观极小的缘故。 -通过把 Debian Linux 操作系统作为开发基础,Valve 得以为 SteamOS 平台找到很多原本就存在与 Steam 平台上的 Linux 兼容游戏来作为“首发游戏”。所以起初大家认为在“首发游戏”上 Steam Machines 对比其他新发布的主机优势明显。然而,很多宣称会在新平台上发布的游戏要么跳票要么被中断了。Rocket League 和 Mad Max 在宣布支持新平台整整一年后才真正发布,而 巫师3 和蝙蝠侠:阿克汉姆骑士 甚至从来没有发布在新平台上。就 巫师3 的情况而言,他们的开发者 CD Projekt Red 拒绝承认他们曾经说过要支持新平台;然而他们的游戏曾在宣布支持 Linux 和 SteamOS 的游戏列表里赫然醒目。雪上加霜的是,很多 AAA 级的大作甚至没被宣布移植,虽然最近这种情况稍有所好转了。 +通过把 Debian Linux 操作系统作为开发基础,Valve 得以为 SteamOS 平台找到很多原本就存在与 Steam 平台上的 Linux 兼容游戏来作为“首发游戏”。所以起初大家认为在“首发游戏”上 Steam Machines 对比其他新发布的主机优势明显。然而,很多宣称会在新平台上发布的游戏要么跳票要么被中断了。Rocket League 和 Mad Max 在宣布支持新平台整整一年后才真正发布,而《巫师 3》和《蝙蝠侠:阿克汉姆骑士》甚至从来没有发布在新平台上。就《巫师 3》的情况而言,他们的开发者 CD Projekt Red 拒绝承认他们曾经说过要支持新平台;然而他们的游戏曾在宣布支持 Linux 和 SteamOS 的游戏列表里赫然醒目。雪上加霜的是,很多 AAA 级的大作甚至没宣布移植,虽然最近这种情况稍有所好转了。 -**被忽视的** +### 被忽视的 -在 Stame Machines 发售后,Valve 的开发者们很快转移到了其他项目的工作中去了。在当时,VR 项目最为被内部所重视,6 月份的时候大约有 1/3 的员工都在相关项目上工作。Valve 把 VR 视为亟待开发的一片领域,而他们的 Steam 则应该作为分发 VR 内容的生态环境。通过与 HTC 合作生产,Valve 设计并制造出了他们自己的 VR 头戴和手柄,并计划在将来更新换代。然而与此同时,Linux 和 Steam Machines 都渐渐淡出了视野。SteamVR 甚至直到最近才刚刚支持 Linux (其实还没对普通消费者开放使用,只在 SteamDevDays 上展示过对 Linux 的支持),而这一点则让我们怀疑 Valve 在 Stame Machines 和 Linux 的开发上是否下定了足够的决心。 +在 Stame Machines 发售后,Valve 的开发者们很快转移到了其他项目的工作中去了。在当时,VR 项目最为内部所重视,6 月份的时候大约有 1/3 的员工都在相关项目上工作。Valve 把 VR 视为亟待开发的一片领域,而他们的 Steam 则应该作为分发 VR 内容的生态环境。通过与 HTC 合作生产,Valve 设计并制造出了他们自己的 VR 头戴和手柄,并计划在将来更新换代。然而与此同时,Linux 和 Steam Machines 都渐渐淡出了视野。SteamVR 甚至直到最近才刚刚支持 Linux (其实还没对普通消费者开放使用,只在 SteamDevDays 上展示过对 Linux 的支持),而这一点则让我们怀疑 Valve 在 Stame Machines 和 Linux 的开发上是否下定了足够的决心。 -SteamOS 自发布以来几乎止步不前。SteamOS 2.0 作为上一个大版本号更新,几乎只是同步了 Debian 上游的变化,而且还需要用户重新安装整个系统,而之后的小补丁也只是在做些上游更新的配合。当 Valve 在其他事关性能和用户体验的项目,例如 Mesa,上进步匪浅的时候,针对 Steam Machines 的相关项目则少有顾及。 +SteamOS 自发布以来几乎止步不前。SteamOS 2.0 作为上一个大版本号更新,几乎只是同步了 Debian 上游的变化,而且还需要用户重新安装整个系统,而之后的小补丁也只是在做些上游更新的配合。当 Valve 在其他事关性能和用户体验的项目(例如 Mesa)上进步匪浅的时候,针对 Steam Machines 的相关项目则少有顾及。 -很多原本应有的功能都从未完成。Steam 的内置功能,例如聊天和直播,都依然处于较弱的状态,而且这种落后会影响所有平台上的 Steam 用户体验。更具体来说,Steam 没有像其他主流主机平台一样把诸如 Netflix,Twitch 和 Spotify 之类的服务集成到客户端里,而通过 Steam 内置的浏览器使用这些服务则体验极差,甚至无法使用;而如果要使用第三方软件则需要开启 Terminal,而且很多软件甚至无法支持控制手柄 —— 无论从哪方面讲这样的用户界面体验都糟糕透顶。 +很多原本应有的功能都从未完成。Steam 的内置功能,例如聊天和直播,都依然处于较弱的状态,而且这种落后会影响所有平台上的 Steam 用户体验。更具体来说,Steam 没有像其他主流主机平台一样把诸如 Netflix、Twitch 和 Spotify 之类的服务集成到客户端里,而通过 Steam 内置的浏览器使用这些服务则体验极差,甚至无法使用;而如果要使用第三方软件则需要开启 Terminal,而且很多软件甚至无法支持控制手柄 —— 无论从哪方面讲这样的用户界面体验都糟糕透顶。 -Valve 同时也几乎没有花任何力气去推广他们的新平台而选择把一切都交由 OEM 厂商们去做。然而,几乎所有 OEM 合作商们要么是高端主机定制商,要么是电脑生产商,要么是廉价电脑公司(译者:简而言之没有一家有大型宣传渠道)。在所有 OEM 中,只有戴尔是 PC 市场的大碗,也只有他们真正给 Steam Machines 做了广告宣传。 +Valve 同时也几乎没有花任何力气去推广他们的新平台,而选择把一切都交由 OEM 厂商们去做。然而,几乎所有 OEM 合作商们要么是高端主机定制商,要么是电脑生产商,要么是廉价电脑公司(LCTT 译注:简而言之没有一家有大型宣传渠道)。在所有 OEM 中,只有戴尔是 PC 市场的大碗,也只有他们真正给 Steam Machines 做了广告宣传。 最终销量也不尽人意。截至 2016 年 6 月,7 个月间 Steam Controller 手柄的销量在包括捆绑销售的情况下仅销售 500,000 件。这让 Steam Machines 的零售情况差到只能被归类到十万俱乐部的最底部。对比已经存在的巨大 PC 和主机游戏平台,可以说销量极低。 -**事后诸葛亮** +### 事后诸葛亮 既然知道了 Steam Machines 的历史,我们又能否总结出失败的原因以及可能存在的翻身改进呢? -_视野与目标_ +#### 视野与目标 -Steam Machines 从来没搞清楚他们在市场里的定位究竟是什么,也从来没说清楚他们具体有何优势。从 PC 市场的角度来说,自己搭建台式机已经非常普及并且往往让电脑的可以匹配玩家自己的目标,同时升级性也非常好。从主机平台的角度来说,Steam Machines 又被主机本身的相对廉价所打败,虽然算上游戏可能稍微便宜一些,但主机上的用户体验也直白很多。 +Steam Machines 从来没搞清楚他们在市场里的定位究竟是什么,也从来没说清楚他们具体有何优势。从 PC 市场的角度来说,自己搭建台式机已经非常普及,并且往往可以让电脑可以匹配玩家自己的目标,同时升级性也非常好。从主机平台的角度来说,Steam Machines 又被主机本身的相对廉价所打败,虽然算上游戏可能稍微便宜一些,但主机上的用户体验也直白很多。 -PC 用户会把多功能性看得很重,他们不仅能用电脑打游戏,也一样能办公和做各种各样的事情。即使 Steam Machines 也是跑着的 SteamOS 操作系统的自由的 Linux 电脑,但操作系统和市场宣传加固了 PC 玩家们对 Steam Machines 是不可定制硬件,低价的更接近主机的印象。即使这些 PC 用户能接受在客厅里购置一台 Steam Machines,他们也有 Steam Link 可以选择,而且很多更小型机比如 NUC 和 Mini-ITX 主板定制机可以让他们搭建更适合放在客厅里的电脑。SteamOS 软件也允许把这些硬件转变为 Steam Machines,但寻求灵活性和兼容性的用户通常都会使用一般 Linux 发行版或者 Windows。二矿最近的 Windows 和 Linux 桌面环境都让维护一般用户的操作系统变得自动化和简单了。 +PC 用户会把多功能性看得很重,他们不仅能用电脑打游戏,也一样能办公和做各种各样的事情。即使 Steam Machines 也是跑着的 SteamOS 操作系统的自由的 Linux 电脑,但操作系统和市场宣传加深了 PC 玩家们对 Steam Machines 是不可定制的硬件、低价的、更接近主机的印象。即使这些 PC 用户能接受在客厅里购置一台 Steam Machines,他们也有 Steam Link 可以选择,而且很多更小型机比如 NUC 和 Mini-ITX 主板定制机可以让他们搭建更适合放在客厅里的电脑。SteamOS 软件也允许把这些硬件转变为 Steam Machines,但寻求灵活性和兼容性的用户通常都会使用一般 Linux 发行版或者 Windows。何况最近的 Windows 和 Linux 桌面环境都让维护一般用户的操作系统变得自动化和简单了。 -电视主机用户们则把易用性放在第一。虽然近年来主机的功能也逐渐扩展,比如可以播放视频或者串流,但总体而言用户还是把即插即用即玩,不用担心兼容性和性能问题和低门槛放在第一。主机的使用寿命也往往较常,一般在 4-7 年左右,而统一固定的硬件也让游戏开发者们能针对其更好的优化和调试软件。现在刚刚新起的中代升级,例如天蝎和 PS 4 Pro 则可能会打破这样统一的游戏体验,但无论如何厂商还是会要求开发者们需要保证游戏在原机型上的体验。为了提高用户粘性,主机也会有自己的社交系统和独占游戏。而主机上的游戏也有实体版,以便将来重用或者二手转卖,这对零售商和用户都是好事儿。Steam Machines 则完全没有这方面的保证;即使长的像一台客厅主机,他们却有 PC 高昂的价格和复杂的硬件情况。 +电视主机用户们则把易用性放在第一。虽然近年来主机的功能也逐渐扩展,比如可以播放视频或者串流,但总体而言用户还是把即插即用即玩、不用担心兼容性和性能问题和低门槛放在第一。主机的使用寿命也往往较长,一般在 4-7 年左右,而统一固定的硬件也让游戏开发者们能针对其更好的优化和调试软件。现在刚刚兴起的中生代升级,例如天蝎和 PS 4 Pro 则可能会打破这样统一的游戏体验,但无论如何厂商还是会要求开发者们需要保证游戏在原机型上的体验。为了提高用户粘性,主机也会有自己的社交系统和独占游戏。而主机上的游戏也有实体版,以便将来重用或者二手转卖,这对零售商和用户都是好事儿。Steam Machines 则完全没有这方面的保证;即使长的像一台客厅主机,他们却有 PC 高昂的价格和复杂的硬件情况。 -_妥协_ +#### 妥协 综上所述,Steam Machines 可以说是“集大成者”,吸取了两边的缺点,又没有自己明确的定位。更糟糕的是 Steam Machines 还展现了 PC 和主机都没有的毛病,比如没有 AAA 大作,又没有 Netflix 这样的客户端。抛开这些不说,Valve 在提高他们产品这件事上几乎没有出力,甚至没有尝试着解决 PC 和主机两头定位矛盾这一点。 @@ -61,35 +61,35 @@ _妥协_ 而最复杂的是 Steam Machines 多变的硬件情况,这使得用户不仅要考虑价格还要考虑配置,还要考虑这个价格下和别的系统(PC 和主机)比起来划算与否。更关键的是,Valve 无论如何也应该做出某种自动硬件检测机制,这样玩家才能知道是否能玩某个游戏,而且这个测试既得简单明了,又要能支持 Steam 上几乎所有游戏。同时,Valve 还要操心未来游戏对配置需求的变化,比如2016 年的 "A" 等主机三年后该给什么评分呢? -_Valve, 个人努力与公司结构_ +#### Valve, 个人努力与公司结构 -尽管 Valve 在 Steam 上创造了辉煌,但其公司的内部结构可能对于开发一个像 Steam Machines 一样的平台是有害的。他们几乎没有领导的自由办公结构,以及所有人都可以自由移动到想要工作的项目组里决定了他们具有极大的创新,研发,甚至开发能力。据说 Valve 只愿意招他们眼中的的 "顶尖人才",通过极其严格的筛选标准,并通过让他们在自己认为“有意义”的项目里工作以保持热情。然而这种思路很可能是错误的;拉帮结派总是存在,而 G胖 的话或许比公司手册上写的还管用,而又有人时不时会由于特殊原因被雇佣或解雇。 +尽管 Valve 在 Steam 上创造了辉煌,但其公司的内部结构可能对于开发一个像 Steam Machines 一样的平台是有害的。他们几乎没有领导的自由办公结构,以及所有人都可以自由移动到想要工作的项目组里决定了他们具有极大的创新,研发,甚至开发能力。据说 Valve 只愿意招他们眼中的的 “顶尖人才”,通过极其严格的筛选标准,并通过让他们在自己认为“有意义”的项目里工作以保持热情。然而这种思路很可能是错误的;拉帮结派总是存在,而 G胖的话或许比公司手册上写的还管用,而又有人时不时会由于特殊原因被雇佣或解雇。 -正因为如此,很多虽不闪闪发光甚至维护起来有些无聊但又需要大量时间的项目很容易枯萎。Valve 的客服已是被人诟病已久的毛病,玩家经常觉得被无视了,而 Valve 则经常不到万不得已法律要求的情况下绝不行动:例如自动退款系统,就是在澳大利亚和欧盟法律的要求下才被加入的;更有目前还没结案的华盛顿州 CS:GO 物品在线赌博网站一案。 +正因为如此,很多虽不闪闪发光甚至维护起来有些无聊但又需要大量时间的项目很容易枯萎。Valve 的客服已是被人诟病已久的毛病,玩家经常觉得被无视了,而 Valve 则经常不到万不得已、法律要求的情况下绝不行动:例如自动退款系统,就是在澳大利亚和欧盟法律的要求下才被加入的;更有目前还没结案的华盛顿州 CS:GO 物品在线赌博网站一案。 各种因素最后也反映在 Steam Machines 这一项目上。Valve 方面的跳票迫使一些合作方做出了尴尬的决定,比如戴尔提前一年发布了 Alienware Alpha 外观的 Steam Machine 就在一年后的正式发布时显得硬件状况落后了。跳票很可能也导致了游戏数量上的问题。开发者和硬件合作商的对跳票和最终毫无轰动的发布也不明朗。Valve 的 VR 平台干脆直接不支持 Linux,而直到最近,SteamVR 都风风火火迭代了好几次之后,SteamOS 和 Linux 依然不支持 VR。 -_“长线钓鱼”_ +#### “长线钓鱼” -尽管 Valve 方面对未来的规划毫无透露,有些人依然认为 Valve 在 Steam Machine 和 SteamOS 上是放长线钓大鱼。他们论点是 Steam 本身也是这样的项目 —— 一开始作为游戏补丁平台出现,到现在无敌的游戏零售和玩家社交网络。虽然 Valve 的独占游戏比如 Half-Life 2 和 CS 也帮助了 Steam 平台的传播。但现今我们完全无法看到 Valve 像当初对 Steam 那样上心 Steam Machines。同时现在 Steam Machines 也面临着 Steam 从没碰到过的激烈竞争。而这些竞争里自然也包含 Valve 自己的那些把 Windows 作为平台的 Steam 客户端。 +尽管 Valve 方面对未来的规划毫无透露,有些人依然认为 Valve 在 Steam Machine 和 SteamOS 上是放长线钓大鱼。他们论点是 Steam 本身也是这样的项目 —— 一开始作为游戏补丁平台出现,到现在无敌的游戏零售和玩家社交网络。虽然 Valve 的独占游戏比如《半条命 2》和 《CS》 也帮助了 Steam 平台的传播。但现今我们完全无法看到 Valve 像当初对 Steam 那样上心 Steam Machines。同时现在 Steam Machines 也面临着 Steam 从没碰到过的激烈竞争。而这些竞争里自然也包含 Valve 自己的那些把 Windows 作为平台的 Steam 客户端。 -_真正目的_ +#### 真正目的 -介于投入在 Steam Machines 上的努力如此之少,有些人怀疑整个产品平台是不是仅仅作为某种博弈的筹码才被开发出来。原初 Steam Machines 就发家于担心微软和苹果通过自己的应用市场垄断游戏的反制手段当中,Valve 寄希望于 Steam Machines 可以在不备之时脱离那些操作系统的支持而运行,同时也是提醒开发者们,也许有一日整个 Steam 平台会独立出来。而当微软和苹果等方面的风口没有继续收紧的情况下,Valve 自然就放慢了开发进度。然而我不这样认为;Valve 其实已经花了不少精力与硬件商和游戏开发者们共同推行这件事,不可能仅仅是为了吓吓他人就终止项目。你可以把这件事想成,微软和 Valve 都在吓唬对方 —— 微软推出了突然收紧的 Windows 8 而 Valve 则展示了一下可以独立门户的能力。 +鉴于投入在 Steam Machines 上的努力如此之少,有些人怀疑整个产品平台是不是仅仅作为某种博弈的筹码才被开发出来。原初 Steam Machines 就发家于担心微软和苹果通过自己的应用市场垄断游戏的反制手段当中,Valve 寄希望于 Steam Machines 可以在不备之时脱离那些操作系统的支持而运行,同时也是提醒开发者们,也许有一日整个 Steam 平台会独立出来。而当微软和苹果等方面的风口没有继续收紧的情况下,Valve 自然就放慢了开发进度。然而我不这样认为;Valve 其实已经花了不少精力与硬件商和游戏开发者们共同推行这件事,不可能仅仅是为了吓吓他人就终止项目。你可以把这件事想成,微软和 Valve 都在吓唬对方 —— 微软推出了突然收紧的 Windows 8 ,而 Valve 则展示了一下可以独立门户的能力。 但即使如此,谁能保证开发者不会愿意跟着微软的封闭环境跑了呢?万一微软最后能提供更好的待遇和用户群体呢?更何况,微软现在正大力推行 Xbox 和 Windows 的交叉和整合,甚至 Xbox 独占游戏也出现在 Windows 上,这一切都没有损害 Windows 原本的平台性定位 —— 谁还能说微软方面不是 Steam 的直接竞争对手呢? -还会有人说这一切一切都是为了推进 Linux 生态环境尽快接纳 PC 游戏,而 Steam Machines 只是想为此大力推一把。但如果是这样,那这个目的实在是性价比极低,因为本愿意支持 Linux 的自然会开发,而 Steam Machines 这一出甚至会让开发者对平台期待额落空从而伤害到他们。 +还会有人说这一切一切都是为了推进 Linux 生态环境尽快接纳 PC 游戏,而 Steam Machines 只是想为此大力推一把。但如果是这样,那这个目的实在是性价比极低,因为本愿意支持 Linux 的自然会开发,而 Steam Machines 这一出甚至会让开发者对平台期待额落空从而伤害到他们。 -**大家眼中 Valve 曾经的机会** +### 大家眼中 Valve 曾经的机会 -我认为 Steam Machines 的创意还是很有趣的,而也有一个与之匹配的市场,但就结果而言 Valve 投入的创意和努力还不够多,而定位模糊也伤害了这个产品。我认为 Steam Machines 的优势在于能砍掉 PC 游戏传统的复杂性,比如硬件问题,整机寿命和维护等;但又能拥有游戏便宜,可以打 Mod 等好处,而且也可以做各种定制化以满足用户需求。但他们必须要让产品的核心内容:价格,市场营销,机型产品线还有软件的质量有所保证才行。 +我认为 Steam Machines 的创意还是很有趣的,而也有一个与之匹配的市场,但就结果而言 Valve 投入的创意和努力还不够多,而定位模糊也伤害了这个产品。我认为 Steam Machines 的优势在于能砍掉 PC 游戏传统的复杂性,比如硬件问题、整机寿命和维护等;但又能拥有游戏便宜,可以打 Mod 等好处,而且也可以做各种定制化以满足用户需求。但他们必须要让产品的核心内容:价格、市场营销、机型产品线还有软件的质量有所保证才行。 -我认为 Steam Machines 可以做出一点妥协,比如硬件升级性(尽管这一点还是有可能被保留下来的 —— 但也要极为小心整个过程对用户体验的影响)和产品选择性,来减少摩擦成本。PC 一直会是一个并列的选项。想给用户产品可选性带来的只有一个困境,成吨的质量低下的 Steam Machines 根本不能解决。Valve 得自己造一台旗舰机型来指明 Steam Machines 的方向。毫无疑问,Alienware 的产品是最接近理想目标的,但他说到底也不是 Valve 的官方之作。Valve 内部不乏优秀的工业设计人才,如果他们愿意投入足够多的重视,我认为结果也许会值得他们努力。而像戴尔和 HTC 这样的公司则可以用他们丰富的经验帮 Valve 制造成品。直接钦定 Steam Machines 的硬件周期,并且在期间只推出 1-2 台机型也有助于帮助解决问题,更不用说他们还可以依次和开发商们确立性能的基准线。我不知道 OEM 合作商们该怎么办;如果 Valve 专注于自己的几台设备里,OEM 们很可能会变得多余甚至拖平台后腿。 +我认为 Steam Machines 可以做出一点妥协,比如硬件升级性(尽管这一点还是有可能被保留下来的 —— 但也要极为小心整个过程对用户体验的影响)和产品选择性,来减少摩擦成本。PC 一直会是一个并列的选项。想给用户产品可选性带来的只有一个困境,成吨的质量低下的 Steam Machines 根本不能解决。Valve 得自己造一台旗舰机型来指明 Steam Machines 的方向。毫无疑问,Alienware 的产品是最接近理想目标的,但它说到底也不是 Valve 的官方之作。Valve 内部不乏优秀的工业设计人才,如果他们愿意投入足够多的重视,我认为结果也许会值得他们努力。而像戴尔和 HTC 这样的公司则可以用他们丰富的经验帮 Valve 制造成品。直接钦定 Steam Machines 的硬件周期,并且在期间只推出 1-2 台机型也有助于帮助解决问题,更不用说他们还可以依次和开发商们确立性能的基准线。我不知道 OEM 合作商们该怎么办;如果 Valve 专注于自己的几台设备里,OEM 们很可能会变得多余甚至拖平台后腿。 -我觉得修复软件问题是最关键的。很多问题在严重拖着 Steam Machines 的后退,比如缺少主机上遍地都是,又能轻易安装在 PC 上的的 Netflix 和 Twitch,即使做好了客厅体验问题依然是严重的败笔。即使 Valve 已经在逐步购买电影的版权以便在 Steam 上发售,我觉得用户还是会倾向于去使用已经在市场上建立口碑的一些串流服务。这些问题需要被严肃地对待,因为玩家日益倾向于把主机作为家庭影院系统的一部分。同时,修复 Steam 客户端和平台的问题也很重要,和更多第三方服务商合作增加内容应该会是个好主意。性能问题和 Linux 下的显卡问题也很严重,不过好在他们最近在慢慢进步。移植游戏也是个问题。类似 Feral Interactive 或者 Aspyr Media 这样的游戏移植商可以帮助扩展 Steam 的商店游戏数量,但联系开发者和出版社可能会有问题,而且这两家移植商经常在移植的容器上搞自己的花样。Valve 已经在帮助游戏工作室自己移植游戏了,比如 Rocket League,不过这种情况很少见,而且就算 Valve 去帮忙了,也是非常符合 Valve 风格的拖拉。而 AAA 大作这一块内容也绝不应该被忽略 —— 近来这方面的情况已经有极大好转了,虽然 Linux 平台的支持好了很多,但在玩家数量不够以及 Valve 为 Steam Machines 提供的开发帮助甚少的情况下,Bethesda 这样的开发商依然不愿意移植游戏;同时,也有像 Denuvo 一样缺乏数字版权管理的公司难以向 Steam Machines 移植游戏。 +我觉得修复软件问题是最关键的。很多问题在严重拖着 Steam Machines 的后腿,比如缺少主机上遍地都是、又能轻易安装在 PC 上的的 Netflix 和 Twitch,那么即使做好了客厅体验问题依然是严重的败笔。即使 Valve 已经在逐步购买电影的版权以便在 Steam 上发售,我觉得用户还是会倾向于去使用已经在市场上建立口碑的一些流媒体服务。这些问题需要被严肃地对待,因为玩家日益倾向于把主机作为家庭影院系统的一部分。同时,修复 Steam 客户端和平台的问题也很重要,和更多第三方服务商合作增加内容应该会是个好主意。性能问题和 Linux 下的显卡问题也很严重,不过好在他们最近在慢慢进步。移植游戏也是个问题。类似 Feral Interactive 或者 Aspyr Media 这样的游戏移植商可以帮助扩展 Steam 的商店游戏数量,但联系开发者和出版社可能会有问题,而且这两家移植商经常在移植的容器上搞自己的花样。Valve 已经在帮助游戏工作室自己移植游戏了,比如 Rocket League,不过这种情况很少见,而且就算 Valve 去帮忙了,也是非常符合 Valve 拖拉的风格。而 AAA 大作这一块内容也绝不应该被忽略 —— 近来这方面的情况已经有极大好转了,虽然 Linux 平台的支持好了很多,但在玩家数量不够以及 Valve 为 Steam Machines 提供的开发帮助甚少的情况下,Bethesda 这样的开发商依然不愿意移植游戏;同时,也有像 Denuvo 一样缺乏数字版权管理的公司难以向 Steam Machines 移植游戏。 -在我看来 Valve 需要在除了软件和硬件的地方也多花些功夫。如果他们只有一个机型的话,他们可以很方便的在硬件生产上贴点钱。这样 Steam Machines 的价格就能跻身主机的行列,而且还能比自己组装 PC 要便宜。针对正确的市场群体做营销也很关键,即便我们还不知道目标玩家应该是谁(我个人会对这样的 Steam Machines 感兴趣,而且我有一整堆已经在 Steam 上以相当便宜的价格买好的游戏)。最后,我觉得零售商们其实不会对 Valve 的计划很感冒,毕竟他们要靠卖和倒卖实体游戏赚钱。 +在我看来 Valve 需要在除了软件和硬件的地方也多花些功夫。如果他们只有一个机型的话,他们可以很方便的在硬件生产上贴点钱。这样 Steam Machines 的价格就能跻身主机的行列,而且还能比自己组装 PC 要便宜。针对正确的市场群体做营销也很关键,即便我们还不知道目标玩家应该是谁(我个人会对这样的 Steam Machines 感兴趣,而且我有一整堆已经在 Steam 上以相当便宜的价格买下的游戏)。最后,我觉得零售商们其实不会对 Valve 的计划很感冒,毕竟他们要靠卖和倒卖实体游戏赚钱。 就算 Valve 在产品和平台上采纳过这些改进,我也不知道怎样才能激活 Steam Machines 的全市场潜力。总的来说,Valve 不仅得学习自己的经验教训,还应该参考曾经有过类似尝试的厂商们,比如尝试依靠开放平台的 3DO 和 Pippin;又或者那些从台式机体验的竞争力退赛的那些公司,其实 Valve 如今的情况和他们也有几分相似。亦或者他们也可以观察一下任天堂 Switch —— 毕竟任天堂也在尝试跨界的创新。 @@ -103,7 +103,7 @@ via: https://www.gamingonlinux.com/articles/user-editorial-steam-machines-steamo 作者:[calvin][a] 译者:[Moelf](https://github.com/Moelf) -校对:[校对者ID](https://github.com/校对者ID) +校对:[wxy](https://github.com/wxy) 本文由 [LCTT](https://github.com/LCTT/TranslateProject) 原创编译,[Linux中国](https://linux.cn/) 荣誉推出 diff --git a/translated/tech/20161223 Will Android do for the IoT what it did for mobile.md b/published/201710/20161223 Will Android do for the IoT what it did for mobile.md similarity index 51% rename from translated/tech/20161223 Will Android do for the IoT what it did for mobile.md rename to published/201710/20161223 Will Android do for the IoT what it did for mobile.md index 7853125d7e..be2c4cbc6f 100644 --- a/translated/tech/20161223 Will Android do for the IoT what it did for mobile.md +++ b/published/201710/20161223 Will Android do for the IoT what it did for mobile.md @@ -1,17 +1,17 @@ - Android 在物联网方面能否像在移动终端一样成功? +Android 在物联网方面能否像在移动终端一样成功? ============================================================ ![](https://cdn-images-1.medium.com/max/1000/1*GF6e6Vd-22PViWT8EDpLNA.jpeg) *Android Things 让 IoT 如虎添翼* -### 我 在Android Things 上的最初 24 小时 +### 我在 Android Things 上的最初 24 小时 -正当我在开发一个基于 Android 的运行在树莓派 3 的物联网商业项目时,一些令人惊喜的事情发生了。谷歌发布了[Android Things][1] 的第一个预览版本,他们的 SDK 专门(目前)针对 3 个 SBC(单板计算机) - 树莓派 3、英特尔 Edison 和恩智浦 Pico。说我一直在挣扎似乎有些轻描淡写 - 没有成功的移植树莓派 Android 可以参照,我们在理想丰满,但是实践漏洞百出的内测版本上叫苦不迭。其中一个问题,同时也是不可原谅的问题是,它不支持触摸屏,甚至连 [Element14][2] 官方销售的也不支持。曾经我认为 Android 已经支持树莓派,更早时候 [commi tto AOSP project from Google][3] 提到过树莓派曾让所有人兴奋不已。所以当 2016 年 12 月 12 日谷歌发布 “Android Things” 和其 SDK 的时候,我马上闭门谢客,全身心地去研究了…… +正当我在开发一个基于 Android 的运行在树莓派 3 的物联网商业项目时,一些令人惊喜的事情发生了。谷歌发布了[Android Things][1] 的第一个预览版本,他们的 SDK 专门(目前)针对 3 个 SBC(单板计算机) —— 树莓派 3、英特尔 Edison 和恩智浦 Pico。说我一直在挣扎似乎有些轻描淡写 —— 树莓派上甚至没有一个成功的 Android 移植版本,我们在理想丰满,但是实践漏洞百出的内测版本上叫苦不迭。其中一个问题,同时也是不可原谅的问题是,它不支持触摸屏,甚至连 [Element14][2] 官方销售的也不支持。曾经我认为 Android 已经支持树莓派,更早时候 “[谷歌向 AOSP 项目发起提交][3]” 中提到过树莓派曾让所有人兴奋不已。所以当 2016 年 12 月 12 日谷歌发布 “Android Things” 及其 SDK 的时候,我马上闭门谢客,全身心地去研究了…… ### 问题? -关于树莓派上的谷歌 Android 我遇到很多问题,我以前用 Android 做过许多开发,也做过一些树莓派项目,包括之前提到过的一个真正参与的。未来我会尝试解决它们,但是首先最重要的问题得到了解决 - 有完整的 Android Studio 支持,树莓派成为你手里的另一个常规的 ADB 可寻址设备。好极了。Android Studio 强大而便利、十分易用的功能包括布局预览、调试系统、源码检查器、自动化测试等都可以真正的应用在 IoT 硬件上。这些好处怎么说都不过分。到目前为止,我在树莓派上的大部分工作都是通过 SSH 使用运行在树莓派上的编辑器(MC,如果你真的想知道)借助 Python 完成的。这是有效的,毫无疑问铁杆的 Pi/Python 粉丝或许会有更好的工作方式,而不是当前这种像极了 80 年代码农的软件开发模式。我的项目需要在控制树莓派的手机上编写 Android 软件,这真有点痛不欲生 - 我使用 Android Studio 做“真正的” Android 开发,借助 SSH 做剩下的。但是有了“Android Things”之后,一切都结束了。 +关于树莓派上的谷歌 Android 我遇到很多问题,我以前用 Android 做过许多开发,也做过一些树莓派项目,包括之前提到过的一个真正参与的。未来我会尝试解决这些问题,但是首先最重要的问题得到了解决 —— 有完整的 Android Studio 支持,树莓派成为你手里的另一个常规的 ADB 可寻址设备。好极了。Android Studio 强大而便利、十分易用的功能包括布局预览、调试系统、源码检查器、自动化测试等都可以真正的应用在 IoT 硬件上。这些好处怎么说都不过分。到目前为止,我在树莓派上的大部分工作都是通过 SSH 使用运行在树莓派上的编辑器(MC,如果你真的想知道)借助 Python 完成的。这是有效的,毫无疑问铁杆的 Pi/Python 粉丝或许会有更好的工作方式,而不是当前这种像极了 80 年代码农的软件开发模式。我的项目需要在控制树莓派的手机上编写 Android 软件,这真有点痛不欲生 —— 我使用 Android Studio 做“真正的” Android 开发,借助 SSH 做剩下的。但是有了“Android Things”之后,一切都结束了。 所有的示例代码都适用于这三种 SBC,树莓派只是其中之一。 `Build.DEVICE` 常量可以在运行时确定是哪一个,所以你会看到很多如下代码: @@ -32,7 +32,7 @@ } ``` -我对 GPIO 处理有浓厚的兴趣。 由于我只熟悉树莓派,我只能假定其他 SBC 工作方式相同,GPIO 只是一组引脚,可以定义为输入/输出,是连接物理外部世界的主要接口。 基于 Linux 的树莓派操作系统通过 Python 中的读取和写入方法提供了完整和便捷的支持,但对于 Android,您必须使用 NDK 编写 C++ 驱动程序,并通过 JNI 在 Java 中与这些驱动程序对接。 不是那么困难,但需要在你的构建链中维护额外的一些东西。 树莓派还为 I2C 指定了 2 个引脚:时钟和数据,因此需要额外的工作来处理它们。I2C 是真正酷的总线寻址系统,它通过串行化将许多独立的数据引脚转换成一个。 所以这里的优势是 - Android Things 已经帮你完成了所有这一切。 你只需要 `read()` 和 `write() ` 你需要的任何 GPIO 引脚,I2C 同样容易: +我对 GPIO 处理有浓厚的兴趣。 由于我只熟悉树莓派,我只能假定其它 SBC 工作方式相同,GPIO 只是一组引脚,可以定义为输入/输出,是连接物理外部世界的主要接口。 基于 Linux 的树莓派操作系统通过 Python 中的读取和写入方法提供了完整和便捷的支持,但对于 Android,您必须使用 NDK 编写 C++ 驱动程序,并通过 JNI 在 Java 中与这些驱动程序对接。 不是那么困难,但需要在你的构建链中维护额外的一些东西。 树莓派还为 I2C 指定了 2 个引脚:时钟和数据,因此需要额外的工作来处理它们。I2C 是真正酷的总线寻址系统,它通过串行化将许多独立的数据引脚转换成一个。 所以这里的优势是 —— Android Things 已经帮你完成了所有这一切。 你只需要 `read()` 和 `write() ` 你需要的任何 GPIO 引脚,I2C 同样容易: ``` public class HomeActivity extends Activity { @@ -73,11 +73,11 @@ public class HomeActivity extends Activity { ### Android Things 基于 Android 的哪个版本? -看起来是 Android 7.0,这样很好,因为我们可以继承 Android 所有以前版本的平板设计 UI、优化,安全加固等。它也带来了一个有趣的问题 - 与应用程序必须单独管理不同,未来的平台应如何更新升级?请记住,这些设备可能无法连接到互联网。我们可能不便于连接蜂窝/ WiFi ,即便之前这些连接能用,但是有时不那么可靠。 +看起来是 Android 7.0,这样很好,因为我们可以继承 Android 所有以前版本的平板设计 UI、优化,安全加固等。它也带来了一个有趣的问题 —— 与应用程序必须单独管理不同,未来的平台应如何更新升级?请记住,这些设备可能无法连接到互联网。我们可能不便于连接蜂窝 / WiFi ,即便之前这些连接能用,但是有时不那么可靠。 -另一个担心是,Android Things 仅仅是一个名字不同的 Android 分支版本,大部分都是一样的,和已经发布的 Arduino 一样,更像为了市场营销而出现,而不是作为操作系统。不过可以放心,实际上通过[样例][4]可以看到,其中一些样例甚至使用了 SVG 图形作为资源,而不是传统的基于位图的图形(当然也能轻松处理) ——这是一个非常新的 Android 创新。 +另一个担心是,Android Things 仅仅是一个名字不同的 Android 分支版本,大部分都是一样的,和已经发布的 Arduino 一样,更像是为了市场营销而出现,而不是作为操作系统。不过可以放心,实际上通过[样例][4]可以看到,其中一些样例甚至使用了 SVG 图形作为资源,而不是传统的基于位图的图形(当然也能轻松处理) —— 这是一个非常新的 Android 创新。 -不可避免地,与 Android Things 相比,普通的 Android 会有些不同。例如,权限问题。因为 Android Things 为固定硬件设计,在构建好之后,用户通常不会在这种设备上安装应用,所以在一定程序上减轻了这个问题,尽管当设备要求权限时是个问题——因为它们没有 UI。解决方案是当应用在安装时给予所有需要的权限。 通常,这些设备只有一个应用,并且该应用从设备上电的那一刻就开始运行。 +不可避免地,与 Android Things 相比,普通的 Android 会有些不同。例如,权限问题。因为 Android Things 为固定硬件设计,在构建好之后,用户通常不会在这种设备上安装应用,所以在一定程序上减轻了这个问题,尽管当设备要求权限时是个问题 —— 因为它们没有 UI。解决方案是当应用在安装时给予所有需要的权限。 通常,这些设备只有一个应用,并且该应用从设备上电的那一刻就开始运行。 ![](https://cdn-images-1.medium.com/max/800/1*pi7HyLT-BVwHQ_Rw3TDSWQ.png) @@ -87,35 +87,35 @@ Brillo 是谷歌以前的 IoT 操作系统的代号,听起来很像 Android Th ### UI 指南? -谷歌针对 Android 智能手机和平板电脑应用发布了大量指南,例如屏幕按钮间距等。 当然,你最好在可行的情况下遵循这些,但这已经不是本文应该考虑的范畴了。 缺省情况下什么也没有 - 应用程序作者决定一切,这包括顶部状态栏,底部导航栏 - 绝对是一切。 多年来谷歌一直在告诉 Android 应用程序的作者们绝不要在屏幕上放置返回按钮,因为平台将提供一个,因为 Android Things [可能甚至没有 UI!] [5] +谷歌针对 Android 智能手机和平板电脑应用发布了大量指南,例如屏幕按钮间距等。 当然,你最好在可行的情况下遵循这些,但这已经不是本文应该考虑的范畴了。 缺省情况下什么也没有 —— 应用程序作者决定一切,这包括顶部状态栏,底部导航栏 —— 绝对是一切。 多年来谷歌一直在告诉 Android 应用程序的作者们绝不要在屏幕上放置返回按钮,因为平台将提供一个,因为 Android Things [可能甚至没有 UI!][5]。 ### 智能手机上会有多少谷歌服务? -有一些,但不是所有。第一个预览版本没有蓝牙支持、没有NFC,这两者都对物联网革命有重大贡献。 SBC 支持它们,所以我们应该不会等待太久。由于没有通知栏,因此不支持任何通知。没有地图。缺省没有软键盘,你必须自己安装一个键盘。由于没有 Play 商店,你只能难受地通过 ADB 做这个和许多其他操作。 +有一些,但不是所有。第一个预览版本没有蓝牙支持、没有 NFC,这两者都对物联网革命有重大贡献。 SBC 支持它们,所以我们应该不会等待太久。由于没有通知栏,因此不支持任何通知。没有地图。缺省没有软键盘,你必须自己安装一个键盘。由于没有 Play 商店,你只能艰难地通过 ADB 做这个和许多其他操作。 -当为 Android Things 开发时,我试图为运行在手机上和树莓派上使用同一个 APK。这引发了一个错误,阻止它安装在除 Android Things 设备之外的任何设备:库 `com.google.android.things` 不存在。 这有点用,因为只有 Android Things 设备需要这个,但它似乎是个限制,因为不仅智能手机或平板电脑上没有,连模拟器上也没有。似乎只能在物理 Android Things 设备上运行和测试您的 Android Things 应用程序……直到谷歌在 [G+ 谷歌的 IoT 开发人员社区][6]组中回答了我的问题,并提供了规避方案。但是,躲过初一,躲不过十五。 +当为 Android Things 开发时,我试图为运行在手机上和树莓派上使用同一个 APK。这引发了一个错误,阻止它安装在除 Android Things 设备之外的任何设备:`com.google.android.things` 库不存在。 这有点用,因为只有 Android Things 设备需要这个,但它似乎是个限制,因为不仅智能手机或平板电脑上没有,连模拟器上也没有。似乎只能在物理 Android Things 设备上运行和测试您的 Android Things 应用程序……直到谷歌在 [G+ 谷歌的 IoT 开发人员社区][6]组中回答了我的问题,并提供了规避方案。但是,躲过初一,躲不过十五。 ### 可以期待 Android Thing 生态演进到什么程度? -我期望看到移植更多传统的基于 Linux 服务器的应用程序,将 Android 限制在智能手机和平板电脑上没有意义。例如,Web 服务器突然变得非常有用。已经有一些了,但没有像重量级的 Apache 或 Nginx。物联网设备可以没有本地 UI,但通过浏览器管理它们当然是可行的,因此需要用这种方式呈现 Web 面板。类似的那些如雷贯耳的通讯应用程序 - 它需要的仅是一个麦克风和扬声器,而且在理论上任何视频通话应用程序,如 Duo、Skype、FB 等都可行。这个演变能走多远目前只能猜测。会有 Play 商店吗?它们会展示广告吗?我们能够确保它们不会窥探我们,或被黑客控制它们么?从消费者的角度来看,物联网应该是具有触摸屏的网络连接设备,因为每个人都已经习惯于通过智能手机工作。 +我期望看到移植更多传统的基于 Linux 服务器的应用程序,将 Android 限制在智能手机和平板电脑上没有意义。例如,Web 服务器突然变得非常有用。已经有一些了,但没有像重量级的 Apache 或 Nginx 的。物联网设备可以没有本地 UI,但通过浏览器管理它们当然是可行的,因此需要用这种方式呈现 Web 面板。类似的那些如雷贯耳的通讯应用程序 —— 它需要的仅是一个麦克风和扬声器,而且在理论上任何视频通话应用程序,如 Duo、Skype、FB 等都可行。这个演变能走多远目前只能猜测。会有 Play 商店吗?它们会展示广告吗?我们能够确保它们不会窥探我们,或被黑客控制它们么?从消费者的角度来看,物联网应该是具有触摸屏的网络连接设备,因为每个人都已经习惯于通过智能手机工作。 -我还期望看到硬件的迅速发展 - 特别是有更多的 SBC 拥有更低的成本。看看惊人的 5 美元 树莓派 Zero,不幸的是,由于其有限的 CPU 和内存,几乎可以肯定不能运行 Android Things。多久之后像这样的设备才能运行 Android Things?这是很明显的,标杆已经设定,任何有追求的 SBC 制造商将瞄准 Android Things 的兼容性,规模经济也将波及到外围设备,如 23 美元的触摸屏。没人会购买不会播放 YouTube 的微波炉,你的洗碗机会在 eBay 上购买更多的清洁粉,因为它注意到你很少使用它…… +我还期望看到硬件的迅速发展 —— 特别是有更多的 SBC 拥有更低的成本。看看惊人的 5 美元树莓派 Zero,不幸的是,由于其有限的 CPU 和内存,几乎可以肯定不能运行 Android Things。多久之后像这样的设备才能运行 Android Things?这是很明显的,标杆已经设定,任何有追求的 SBC 制造商将瞄准 Android Things 的兼容性,规模经济也将波及到外围设备,如 23 美元的触摸屏。没人会购买不会播放 YouTube 的微波炉,你的洗碗机会在 eBay 上购买更多的清洁粉,因为它注意到你很少使用它…… -然而,我不认为我们会过于冲昏头脑。了解一点 Android 架构有助于将其视为一个包罗万象的物联网操作系统。它仍然使用 Java,其垃圾回收机制导致的所有时序问题在过去几乎把它搞死。这仅仅是问题最少的部分。真正的实时操作系统依赖于可预测、准确和坚如磐石的时序,或者它不能被用于“关键任务”。想想医疗应用、安全监视器,工业控制器等。使用 Android,如果宿主操作系统认为它需要,理论上可以在任何时候杀死您的活动/服务。这在手机上没那么糟糕 - 用户可以重新启动应用程序,杀死其他应用程序,或重新启动手机。但心脏监视器就完全是另一码事。如果前台的活动/服务正在监视一个 GPIO 引脚,而这个信号没有被准确地处理,我们就完了。必须要做一些相当根本的改变让 Android 来支持这一点,到目前为止还没有迹象表明它已经在计划之中了。 +然而,我不认为我们会过于冲昏头脑。了解一点 Android 架构有助于将其视为一个包罗万象的物联网操作系统。它仍然使用 Java,其垃圾回收机制导致的所有时序问题在过去几乎把它搞死。这仅仅是问题最少的部分。真正的实时操作系统依赖于可预测、准确和坚如磐石的时序,要么它就不能被用于“关键任务”。想想医疗应用、安全监视器,工业控制器等。使用 Android,如果宿主操作系统认为它需要,理论上可以在任何时候杀死您的活动/服务。这在手机上没那么糟糕 —— 用户可以重新启动应用程序,杀死其他应用程序,或重新启动手机。但心脏监视器就完全是另一码事。如果前台的活动/服务正在监视一个 GPIO 引脚,而这个信号没有被准确地处理,我们就完了。必须要做一些相当根本的改变让 Android 来支持这一点,到目前为止还没有迹象表明它已经在计划之中了。 -###这 24 小时 +### 这 24 小时 -所以,回到我的项目。 我认为我会接管我已经完成和尽力能为的工作,等待不可避免的路障,并向 G+ 社区寻求帮助。 除了一些在非 Android Things 设备上如何运行程序的问题之外,没有其他问题。 它运行得很好! 这个项目也使用了一些奇怪的东西,如自定义字体、高精定时器 - 所有这些都在 Android Studio 中完美地展现。对我而言,可以打满分 - 至少我能够开始做出实际原型,而不只是视频和截图。 +所以,回到我的项目。 我认为我会接管我已经完成和尽力能为的工作,等待不可避免的路障,并向 G+ 社区寻求帮助。 除了一些在非 Android Things 设备上如何运行程序的问题之外,没有其他问题。它运行得很好! 这个项目也使用了一些奇怪的东西,如自定义字体、高精定时器 —— 所有这些都在 Android Studio 中完美地展现。对我而言,可以打满分 —— 至少我能够开始做出实际原型,而不只是视频和截图。 ### 蓝图 -今天的物联网操作系统环境看起来非常零碎。 显然没有市场领导者,尽管炒作之声沸反连天,物联网仍然在草创阶段。 谷歌 Android 物联网能否像它在移动端那样取得成功?现在 Android 在移动方面的主导地位非常接近 90%。我相信如果真的如此,Android Things 的推出正是重要的一步。 +今天的物联网操作系统环境看起来非常零碎。 显然没有市场领导者,尽管炒作之声沸反连天,物联网仍然在草创阶段。 谷歌 Android 物联网能否像它在移动端那样取得成功?现在 Android 在移动方面的主导地位几近达到 90%。我相信如果真的如此,Android Things 的推出正是重要的一步。 记住所有的关于开放和封闭软件的战争,它们主要发生在从不授权的苹果和一直担心免费还不够充分的谷歌之间。那个老梗又来了,因为让苹果推出一个免费的物联网操作系统的构想就像让他们免费赠送下一代 iPhone 一样遥不可及。 物联网操作系统游戏是开放的,大家机遇共享,不过这个时候,封闭派甚至不会公布它们的开发工具箱…… -转到 [Developer Preview][7]网站,立即获取 Android Things SDK 的副本。 +前往 [Developer Preview][7]网站,立即获取 Android Things SDK 的副本。 -------------------------------------------------------------------------------- diff --git a/published/201710/2017 Cloud Integrated Advanced Orchestrator.md b/published/201710/2017 Cloud Integrated Advanced Orchestrator.md new file mode 100644 index 0000000000..0d704b8734 --- /dev/null +++ b/published/201710/2017 Cloud Integrated Advanced Orchestrator.md @@ -0,0 +1,35 @@ +Ciao:云集成高级编排器 +============================================================ + +云集成高级编排器Cloud Integrated Advanced Orchestrator (Ciao) 是一个新的负载调度程序,用来解决当前云操作系统项目的局限性。Ciao 提供了一个轻量级,完全基于 TLS 的最小配置。它是 +工作量无关的、易于更新、具有优化速度的调度程序,目前已针对 OpenStack 进行了优化。 + +其设计决策和创新方法在对安全性、可扩展性、可用性和可部署性的要求下进行: + +- **可扩展性:** 初始设计目标是伸缩超过 5,000 个节点。因此,调度器架构用新的形式实现: + - 在 ciao 中,决策制定是去中心化的。它基于拉取模型,允许计算节点从调度代理请求作业。调度程序总能知道启动器的容量,而不要求进行数据更新,并且将调度决策时间保持在最小。启动器异步向调度程序发送容量。 + - 持久化状态跟踪与调度程序决策制定相分离,它让调度程序保持轻量级。这种分离增加了可靠性、可扩展性和性能。结果是调度程序让出了权限并且这不是瓶颈。 +- **可用性:** 虚拟机、容器和裸机集成到一个调度器中。所有的负载都被视为平等公民。为了更易于使用,网络通过一个组件间最小化的异步协议进行简化,只需要最少的配置。Ciao 还包括一个新的、简单的 UI。所有的这些功能都集成到一起来简化安装、配置、维护和操作。 +- **轻松部署:** 升级应该是预期操作,而不是例外情况。这种新的去中心化状态的体系结构能够无缝升级。为了确保基础设施(例如 OpenStack)始终是最新的,它实现了持续集成/持续交付(CI/CD)模型。Ciao 的设计使得它可以立即杀死任何 Ciao 组件,更换它,并重新启动它,对可用性影响最小。 +- **安全性是必需的:** 与调度程序的连接总是加密的:默认情况下 SSL 是打开的,而不是关闭的。加密是从端到端:所有外部连接都需要 HTTPS,组件之间的内部通信是基于 TLS 的。网络支持的一体化保障了租户分离。 + +初步结果证明是显著的:在 65 秒内启动一万个 Docker 容器和五千个虚拟机。进一步优化还在进行。 + +- 文档:[https://clearlinux.org/documentation/ciao/ciao.html][3] +- Github 链接: [https://github.com/01org/ciao(link is external)][1] +- 邮件列表链接: [https://lists.clearlinux.org/mailman/listinfo/ciao-devel][2] + +-------------------------------------------------------------------------------- + +via: https://clearlinux.org/ciao + +作者:[ciao][a] +译者:[geekpi](https://github.com/geekpi) +校对:[wxy](https://github.com/wxy) + +本文由 [LCTT](https://github.com/LCTT/TranslateProject) 原创编译,[Linux中国](https://linux.cn/) 荣誉推出 + +[a]:https://clearlinux.org/ciao +[1]:https://github.com/01org/ciao +[2]:https://lists.clearlinux.org/mailman/listinfo/ciao-devel +[3]:https://clearlinux.org/documentation/ciao/ciao.html diff --git a/published/201710/20170109 Server-side IO Performance Node vs. PHP vs. Java vs. Go.md b/published/201710/20170109 Server-side IO Performance Node vs. PHP vs. Java vs. Go.md new file mode 100644 index 0000000000..48aab9ec70 --- /dev/null +++ b/published/201710/20170109 Server-side IO Performance Node vs. PHP vs. Java vs. Go.md @@ -0,0 +1,287 @@ +服务端 I/O 性能:Node、PHP、Java、Go 的对比 +============ + +了解应用程序的输入/输出(I/O)模型意味着理解应用程序处理其数据的载入差异,并揭示其在真实环境中表现。或许你的应用程序很小,在不承受很大的负载时,这并不是个严重的问题;但随着应用程序的流量负载增加,可能因为使用了低效的 I/O 模型导致承受不了而崩溃。 + +和大多数情况一样,处理这种问题的方法有多种方式,这不仅仅是一个择优的问题,而是对权衡的理解问题。 接下来我们来看看 I/O 到底是什么。 + +![Cover Photo: Server-side I/O: Node vs. PHP vs. Java vs. Go](https://uploads.toptal.io/blog/image/123050/toptal-blog-image-1494506620527-88162414141f3b3627e6f8dacbea29f0.jpg) + +在本文中,我们将对 Node、Java、Go 和 PHP + Apache 进行对比,讨论不同语言如何构造其 I/O ,每个模型的优缺点,并总结一些基本的规律。如果你担心你的下一个 Web 应用程序的 I/O 性能,本文将给你最优的解答。 + +### I/O 基础知识: 快速复习 + +要了解 I/O 所涉及的因素,我们首先深入到操作系统层面复习这些概念。虽然看起来并不与这些概念直接打交道,但你会一直通过应用程序的运行时环境与它们间接接触。了解细节很重要。 + +#### 系统调用 + +首先是系统调用,其被描述如下: + +* 程序(所谓“用户端user land”)必须请求操作系统内核代表它执行 I/O 操作。 +* “系统调用syscall”是你的程序要求内核执行某些操作的方法。这些实现的细节在操作系统之间有所不同,但基本概念是相同的。有一些具体的指令会将控制权从你的程序转移到内核(类似函数调用,但是使用专门用于处理这种情况的专用方式)。一般来说,系统调用会被阻塞,这意味着你的程序会等待内核返回(控制权到)你的代码。 +* 内核在所需的物理设备( 磁盘、网卡等 )上执行底层 I/O 操作,并回应系统调用。在实际情况中,内核可能需要做许多事情来满足你的要求,包括等待设备准备就绪、更新其内部状态等,但作为应用程序开发人员,你不需要关心这些。这是内核的工作。 + +![Syscalls Diagram](https://uploads.toptal.io/blog/image/123021/toptal-blog-image-1494484316720-491f79a78eb5c6c419aec0971955cc31.jpg) + +#### 阻塞与非阻塞 + +上面我们提到过,系统调用是阻塞的,一般来说是这样的。然而,一些调用被归类为“非阻塞”,这意味着内核会接收你的请求,将其放在队列或缓冲区之类的地方,然后立即返回而不等待实际的 I/O 发生。所以它只是在很短的时间内“阻塞”,只需要排队你的请求即可。 + +举一些 Linux 系统调用的例子可能有助于理解: + +- `read()` 是一个阻塞调用 - 你传递一个句柄,指出哪个文件和缓冲区在哪里传送它所读取的数据,当数据就绪时,该调用返回。这种方式的优点是简单友好。 +- 分别调用 `epoll_create()`、`epoll_ctl()` 和 `epoll_wait()` ,你可以创建一组句柄来侦听、添加/删除该组中的处理程序、然后阻塞直到有任何事件发生。这允许你通过单个线程有效地控制大量的 I/O 操作,但是现在谈这个还太早。如果你需要这个功能当然好,但须知道它使用起来是比较复杂的。 + +了解这里的时间差异的数量级是很重要的。假设 CPU 内核运行在 3GHz,在没有进行 CPU 优化的情况下,那么它每秒执行 30 亿次周期cycle(即每纳秒 3 个周期)。非阻塞系统调用可能需要几十个周期来完成,或者说 “相对少的纳秒” 时间完成。而一个被跨网络接收信息所阻塞的系统调用可能需要更长的时间 - 例如 200 毫秒(1/5 秒)。这就是说,如果非阻塞调用需要 20 纳秒,阻塞调用需要 2 亿纳秒。你的进程因阻塞调用而等待了 1000 万倍的时长! + +![Blocking vs. Non-blocking Syscalls](https://uploads.toptal.io/blog/image/123022/toptal-blog-image-1494484326798-0372c535867b3c829329692d3b8a1a21.jpg) + +内核既提供了阻塞 I/O (“从网络连接读取并给出数据”),也提供了非阻塞 I/O (“告知我何时这些网络连接具有新数据”)的方法。使用的是哪种机制对调用进程的阻塞时长有截然不同的影响。 + +#### 调度 + +关键的第三件事是当你有很多线程或进程开始阻塞时会发生什么。 + +根据我们的理解,线程和进程之间没有很大的区别。在现实生活中,最显著的性能相关的差异在于,由于线程共享相同的内存,而进程每个都有自己的内存空间,使得单独的进程往往占用更多的内存。但是当我们谈论调度Scheduling时,它真正归结为一类事情(线程和进程类同),每个都需要在可用的 CPU 内核上获得一段执行时间。如果你有 300 个线程运行在 8 个内核上,则必须将时间分成几份,以便每个线程和进程都能分享它,每个运行一段时间,然后交给下一个。这是通过 “上下文切换context switch” 完成的,可以使 CPU 从运行到一个线程/进程到切换下一个。 + +这些上下文切换也有相关的成本 - 它们需要一些时间。在某些快速的情况下,它可能小于 100 纳秒,但根据实际情况、处理器速度/体系结构、CPU 缓存等,偶见花费 1000 纳秒或更长时间。 + +而线程(或进程)越多,上下文切换就越多。当我们涉及数以千计的线程时,每个线程花费数百纳秒,就会变得很慢。 + +然而,非阻塞调用实质上是告诉内核“仅在这些连接之一有新的数据或事件时再叫我”。这些非阻塞调用旨在有效地处理大量 I/O 负载并减少上下文交换。 + +这些你明白了么?现在来到了真正有趣的部分:我们来看看一些流行的语言对那些工具的使用,并得出关于易用性和性能之间权衡的结论,以及一些其他有趣小东西。 + +声明,本文中显示的示例是零碎的(片面的,只能体现相关的信息); 数据库访问、外部缓存系统( memcache 等等)以及任何需要 I/O 的东西都将执行某种类型的 I/O 调用,其实质与上面所示的简单示例效果相同。此外,对于将 I/O 描述为“阻塞”( PHP、Java )的情况,HTTP 请求和响应读取和写入本身就是阻塞调用:系统中隐藏着更多 I/O 及其伴生的性能问题需要考虑。 + +为一个项目选择编程语言要考虑很多因素。甚至当你只考虑效率时,也有很多因素。但是,如果你担心你的程序将主要受到 I/O 的限制,如果 I/O 性能影响到项目的成败,那么这些是你需要了解的。 + +### “保持简单”方法:PHP + +早在 90 年代,很多人都穿着 [Converse][1] 鞋,用 Perl 写着 CGI 脚本。然后 PHP 来了,就像一些人喜欢咒骂的一样,它使得动态网页更容易。 + +PHP 使用的模型相当简单。虽有一些出入,但你的 PHP 服务器基本上是这样: + +HTTP 请求来自用户的浏览器,并访问你的 Apache Web 服务器。Apache 为每个请求创建一个单独的进程,有一些优化方式可以重新使用它们,以最大限度地减少创建次数( 相对而言,创建进程较慢 )。Apache 调用 PHP 并告诉它运行磁盘上合适的 `.php` 文件。PHP 代码执行并阻塞 I/O 调用。你在 PHP 中调用 `file_get_contents()` ,其底层会调用 `read()` 系统调用并等待结果。 + +当然,实际的代码是直接嵌入到你的页面,并且该操作被阻塞: + +``` +query('SELECT id, data FROM examples ORDER BY id DESC limit 100'); + +?> + +``` + +关于如何与系统集成,就像这样: + +![I/O Model PHP](https://uploads.toptal.io/blog/image/123049/toptal-blog-image-1494505840356-b8a0d78356a18a040600cad68d52b7ae.jpg) + +很简单:每个请求一个进程。 I/O 调用就阻塞。优点是简单可工作,缺点是,同时与 20,000 个客户端连接,你的服务器将会崩溃。这种方法不能很好地扩展,因为内核提供的用于处理大容量 I/O (epoll 等) 的工具没有被使用。 雪上加霜的是,为每个请求运行一个单独的进程往往会使用大量的系统资源,特别是内存,这通常是你在这样的场景中遇到的第一个问题。 + +_注意:Ruby 使用的方法与 PHP 非常相似,在大致的方面上,它们可以被认为是相同的。_ + +### 多线程方法: Java + +就在你购买你的第一个域名,在某个句子后很酷地随机说出 “dot com” 的那个时候,Java 来了。而 Java 具有内置于该语言中的多线程功能,它非常棒(特别是在创建时)。 + +大多数 Java Web 服务器通过为每个请求启动一个新的执行线程,然后在该线程中最终调用你(作为应用程序开发人员)编写的函数。 + +在 Java Servlet 中执行 I/O 往往看起来像: + +``` +public void doGet(HttpServletRequest request, + HttpServletResponse response) throws ServletException, IOException +{ + + // blocking file I/O + InputStream fileIs = new FileInputStream("/path/to/file"); + + // blocking network I/O + URLConnection urlConnection = (new URL("http://example.com/example-microservice")).openConnection(); + InputStream netIs = urlConnection.getInputStream(); + + // some more blocking network I/O +out.println("..."); +} +``` + +由于我们上面的 `doGet` 方法对应于一个请求,并且在其自己的线程中运行,而不是每个请求一个单独的进程,申请自己的内存。这样有一些好处,比如在线程之间共享状态、缓存数据等,因为它们可以访问彼此的内存,但是它与调度的交互影响与之前的 PHP 的例子几乎相同。每个请求获得一个新线程,该线程内的各种 I/O 操作阻塞在线程内,直到请求被完全处理为止。线程被池化以最小化创建和销毁它们的成本,但是数千个连接仍然意味着数千个线程,这对调度程序是不利的。 + +重要的里程碑出现在 Java 1.4 版本(以及 1.7 的重要升级)中,它获得了执行非阻塞 I/O 调用的能力。大多数应用程序、web 应用和其它用途不会使用它,但至少它是可用的。一些 Java Web 服务器尝试以各种方式利用这一点;然而,绝大多数部署的 Java 应用程序仍然如上所述工作。 + +![I/O Model Java](https://uploads.toptal.io/blog/image/123024/toptal-blog-image-1494484354611-f68fb1694b52ffd8ea112ec2fb5570c0.jpg) + +肯定有一些很好的开箱即用的 I/O 功能,Java 让我们更接近,但它仍然没有真正解决当你有一个大量的 I/O 绑定的应用程序被数千个阻塞线程所压垮的问题。 + +### 无阻塞 I/O 作为一等公民: Node + +当更好的 I/O 模式来到 Node.js,阻塞才真正被解决。任何一个曾听过 Node 简单介绍的人都被告知这是“非阻塞”,可以有效地处理 I/O。这在一般意义上是正确的。但在细节中则不尽然,而且当在进行性能工程时,这种巫术遇到了问题。 + +Node 实现的范例基本上不是说 “在这里写代码来处理请求”,而是说 “在这里写代码来**开始**处理请求”。每次你需要做一些涉及到 I/O 的操作,你会创建一个请求并给出一个回调函数,Node 将在完成之后调用该函数。 + +在请求中执行 I/O 操作的典型 Node 代码如下所示: + +``` +http.createServer(function(request, response) { + fs.readFile('/path/to/file', 'utf8', function(err, data) { + response.end(data); + }); +}); + +``` + +你可以看到,这里有两个回调函数。当请求开始时,第一个被调用,当文件数据可用时,第二个被调用。 + +这样做的基本原理是让 Node 有机会有效地处理这些回调之间的 I/O 。一个更加密切相关的场景是在 Node 中进行数据库调用,但是我不会在这个例子中啰嗦,因为它遵循完全相同的原则:启动数据库调用,并给 Node 一个回调函数,它使用非阻塞调用单独执行 I/O 操作,然后在你要求的数据可用时调用回调函数。排队 I/O 调用和让 Node 处理它然后获取回调的机制称为“事件循环”。它工作的很好。 + +![I/O Model Node.js](https://uploads.toptal.io/blog/image/123025/toptal-blog-image-1494484364927-0869f1e8acd49501f676dffef7f3c642.jpg) + +然而,这个模型有一个陷阱,究其原因,很多是与 V8 JavaScript 引擎(Node 用的是 Chrome 浏览器的 JS 引擎)如何实现的有关^注1 。你编写的所有 JS 代码都运行在单个线程中。你可以想想,这意味着当使用高效的非阻塞技术执行 I/O 时,你的 JS 可以在单个线程中运行计算密集型的操作,每个代码块都会阻塞下一个。可能出现这种情况的一个常见例子是以某种方式遍历数据库记录,然后再将其输出到客户端。这是一个示例,展示了其是如何工作: + +``` +var handler = function(request, response) { + + connection.query('SELECT ...', function (err, rows) { + + if (err) { throw err }; + + for (var i = 0; i < rows.length; i++) { + // do processing on each row + } + + response.end(...); // write out the results + + }) + +}; +``` + +虽然 Node 确实有效地处理了 I/O ,但是上面的例子中 `for` 循环是在你的唯一的一个主线程中占用 CPU 周期。这意味着如果你有 10,000 个连接,则该循环可能会使你的整个应用程序像爬行般缓慢,具体取决于其会持续多久。每个请求必须在主线程中分享一段时间,一次一段。 + +这整个概念的前提是 I/O 操作是最慢的部分,因此最重要的是要有效地处理这些操作,即使这意味着要连续进行其他处理。这在某些情况下是正确的,但不是全部。 + +另一点是,虽然这只是一个观点,但是写一堆嵌套的回调可能是相当令人讨厌的,有些则认为它使代码更难以追踪。在 Node 代码中看到回调嵌套 4 层、5 层甚至更多层并不罕见。 + +我们再次来权衡一下。如果你的主要性能问题是 I/O,则 Node 模型工作正常。然而,它的关键是,你可以在一个处理 HTTP 请求的函数里面放置 CPU 密集型的代码,而且不小心的话会导致每个连接都很慢。 + +### 最自然的非阻塞:Go + +在我进入 Go 部分之前,我应该披露我是一个 Go 的粉丝。我已经在许多项目中使用过它,我是一个其生产力优势的公开支持者,我在我的工作中使用它。 + +那么,让我们来看看它是如何处理 I/O 的。Go 语言的一个关键特征是它包含自己的调度程序。在 Go 中,不是每个执行线程对应于一个单一的 OS 线程,其通过一种叫做 “协程goroutine” 的概念来工作。而 Go 的运行时可以将一个协程分配给一个 OS 线程,使其执行或暂停它,并且它不与一个 OS 线程相关联——这要基于那个协程正在做什么。来自 Go 的 HTTP 服务器的每个请求都在单独的协程中处理。 + +调度程序的工作原理如图所示: + +![I/O Model Go](https://uploads.toptal.io/blog/image/123026/toptal-blog-image-1494484377088-fdcc99ced01713937ff76afc9b56416c.jpg) + +在底层,这是通过 Go 运行时中的各个部分实现的,它通过对请求的写入/读取/连接等操作来实现 I/O 调用,将当前协程休眠,并当采取进一步动作时唤醒该协程。 + +从效果上看,Go 运行时做的一些事情与 Node 做的没有太大不同,除了回调机制是内置到 I/O 调用的实现中,并自动与调度程序交互。它也不会受到必须让所有处理程序代码在同一个线程中运行的限制,Go 将根据其调度程序中的逻辑自动将协程映射到其认为适当的 OS 线程。结果是这样的代码: + +``` +func ServeHTTP(w http.ResponseWriter, r *http.Request) { + + // the underlying network call here is non-blocking + rows, err := db.Query("SELECT ...") + + for _, row := range rows { + // do something with the rows, +// each request in its own goroutine + } + + w.Write(...) // write the response, also non-blocking + +} + +``` + +如上所述,我们重构基本的代码结构为更简化的方式,并在底层仍然实现了非阻塞 I/O。 + +在大多数情况下,最终是“两全其美”的。非阻塞 I/O 用于所有重要的事情,但是你的代码看起来像是阻塞,因此更容易理解和维护。Go 调度程序和 OS 调度程序之间的交互处理其余部分。这不是完整的魔法,如果你建立一个大型系统,那么值得我们来看看有关它的工作原理的更多细节;但与此同时,你获得的“开箱即用”的环境可以很好地工作和扩展。 + +Go 可能有其缺点,但一般来说,它处理 I/O 的方式不在其中。 + +### 谎言,可恶的谎言和基准 + +对这些各种模式的上下文切换进行准确的定时是很困难的。我也可以认为这对你来说不太有用。相反,我会给出一些比较这些服务器环境的整个 HTTP 服务器性能的基本基准。请记住,影响整个端到端 HTTP 请求/响应路径的性能有很多因素,这里提供的数字只是我将一些样本放在一起进行基本比较的结果。 + +对于这些环境中的每一个,我写了适当的代码在一个 64k 文件中读取随机字节,在其上运行了一个 SHA-256 哈希 N 次( N 在 URL 的查询字符串中指定,例如 .../test.php?n=100),并打印出结果十六进制散列。我选择这样做,是因为使用一些一致的 I/O 和受控的方式来运行相同的基准测试是一个增加 CPU 使用率的非常简单的方法。 + +有关使用的环境的更多细节,请参阅 [基准说明][3] 。 + +首先,我们来看一些低并发的例子。运行 2000 次迭代,300 个并发请求,每个请求只有一个散列(N = 1),结果如下: + +![Mean number of milliseconds to complete a request across all concurrent requests, N=1](https://uploads.toptal.io/blog/image/123027/toptal-blog-image-1494484391296-b9fa90935e5892036d8e30b4950ed448.jpg) + +*时间是在所有并发请求中完成请求的平均毫秒数。越低越好。* + +仅从一张图很难得出结论,但是对我来说,似乎在大量的连接和计算量上,我们看到时间更多地与语言本身的一般执行有关,对于 I/O 更是如此。请注意,那些被视为“脚本语言”的语言(松散类型,动态解释)执行速度最慢。 + +但是,如果我们将 N 增加到 1000,仍然有 300 个并发请求,相同的任务,但是哈希迭代是 1000 倍(显着增加了 CPU 负载): + +![Mean number of milliseconds to complete a request across all concurrent requests, N=1000](https://uploads.toptal.io/blog/image/123028/toptal-blog-image-1494484399553-e808d736ed165a362c8ad101a9486fe5.jpg) + +*时间是在所有并发请求中完成请求的平均毫秒数。越低越好。* + +突然间, Node 性能显著下降,因为每个请求中的 CPU 密集型操作都相互阻塞。有趣的是,在这个测试中,PHP 的性能要好得多(相对于其他的),并且打败了 Java。(值得注意的是,在 PHP 中,SHA-256 实现是用 C 编写的,在那个循环中执行路径花费了更多的时间,因为现在我们正在进行 1000 个哈希迭代)。 + +现在让我们尝试 5000 个并发连接(N = 1) - 或者是我可以发起的最大连接。不幸的是,对于大多数这些环境,故障率并不显着。对于这个图表,我们来看每秒的请求总数。 _越高越好_ : + +![Total number of requests per second, N=1, 5000 req/sec](https://uploads.toptal.io/blog/image/123029/toptal-blog-image-1494484407612-527f9a22d54c1d30738d7cd3fe41e415.jpg) + +*每秒请求数。越高越好。* + +这个图看起来有很大的不同。我猜测,但是看起来像在高连接量时,产生新进程所涉及的每连接开销以及与 PHP + Apache 相关联的附加内存似乎成为主要因素,并阻止了 PHP 的性能。显然,Go 是这里的赢家,其次是 Java,Node,最后是 PHP。 + +虽然与你的整体吞吐量相关的因素很多,并且在应用程序之间也有很大的差异,但是你对底层发生什么的事情以及所涉及的权衡了解更多,你将会得到更好的结果。 + +### 总结 + +以上所有这一切,很显然,随着语言的发展,处理大量 I/O 的大型应用程序的解决方案也随之发展。 + +为了公平起见,PHP 和 Java,尽管这篇文章中的描述,确实 [实现了][4] 在 [ web 应用程序][7] 中 [可使用的][6] [ 非阻塞 I/O][5] 。但是这些方法并不像上述方法那么常见,并且需要考虑使用这种方法来维护服务器的随之而来的操作开销。更不用说你的代码必须以与这些环境相适应的方式进行结构化;你的 “正常” PHP 或 Java Web 应用程序通常不会在这样的环境中进行重大修改。 + +作为比较,如果我们考虑影响性能和易用性的几个重要因素,我们得出以下结论: + +| 语言 | 线程与进程 | 非阻塞 I/O | 使用便捷性 | +| --- | --- | --- | --- | +| PHP | 进程 | 否 | | +| Java | 线程 | 可用 | 需要回调 | +| Node.js | 线程 | 是 | 需要回调 | +| Go | 线程 (协程) | 是 | 不需要回调 | + +线程通常要比进程有更高的内存效率,因为它们共享相同的内存空间,而进程则没有。结合与非阻塞 I/O 相关的因素,我们可以看到,至少考虑到上述因素,当我们从列表往下看时,与 I/O 相关的一般设置得到改善。所以如果我不得不在上面的比赛中选择一个赢家,那肯定会是 Go。 + +即使如此,在实践中,选择构建应用程序的环境与你的团队对所述环境的熟悉程度以及你可以实现的总体生产力密切相关。因此,每个团队都深入并开始在 Node 或 Go 中开发 Web 应用程序和服务可能就没有意义。事实上,寻找开发人员或你内部团队的熟悉度通常被认为是不使用不同语言和/或环境的主要原因。也就是说,过去十五年来,时代已经发生了变化。 + +希望以上内容可以帮助你更清楚地了解底层发生的情况,并为你提供如何处理应用程序的现实可扩展性的一些想法。 + +-------------------------------------------------------------------------------- + +via: https://www.toptal.com/back-end/server-side-io-performance-node-php-java-go + +作者:[BRAD PEABODY][a] +译者:[MonkeyDEcho](https://github.com/MonkeyDEcho) +校对:[wxy](https://github.com/wxy) + +本文由 [LCTT](https://github.com/LCTT/TranslateProject) 原创编译,[Linux中国](https://linux.cn/) 荣誉推出 + +[a]:https://www.toptal.com/resume/brad-peabody +[1]:https://www.pinterest.com/pin/414401603185852181/ +[2]:http://www.journaldev.com/7462/node-js-architecture-single-threaded-event-loop +[3]:https://peabody.io/post/server-env-benchmarks/ +[4]:http://reactphp.org/ +[5]:http://amphp.org/ +[6]:http://undertow.io/ +[7]:https://netty.io/ diff --git a/published/201710/20170126 A 5-step plan to encourage your team to make changes on your project.md b/published/201710/20170126 A 5-step plan to encourage your team to make changes on your project.md new file mode 100644 index 0000000000..5f050cf63b --- /dev/null +++ b/published/201710/20170126 A 5-step plan to encourage your team to make changes on your project.md @@ -0,0 +1,86 @@ +促使项目团队作出改变的五步计划 +============================================================ + + ![促使项目团队作出改变的五步计划](https://opensource.com/sites/default/files/styles/image-full-size/public/images/business/BIZ_Maze2.png?itok=egeRn990 "五步的计划促使项目团队作出改变") + +目的是任何团队组建的首要之事。如果一个人足以实现那个目的,那么就没有必要组成团队。而且如果没有重要目标,你根本不需要一个团队。但只要任务需要的专业知识比一个人所拥有的更多,我们就会遇到集体参与的问题——如果处理不当,会使你脱离正轨。 + +想象一群人困在洞穴中。没有一个人具备如何出去的全部知识,所以每个人要协作,心路常开,在想要做的事情上尽力配合。当(且仅当)组建了适当的工作团队之后,才能为实现团队的共同目标创造出合适的环境。 + +但确实有人觉得待在洞穴中很舒适而且只想待在那里。在组织里,领导者们如何掌控那些实际上抵触改善、待在洞穴中觉得舒适的人?同时该如何找到拥有共同目标但是不在自己组织的人? + +我从事指导国际销售培训,刚开始甚至很少有人认为我的工作有价值。所以,我想出一套使他们信服的战术。那个战术非常成功以至于我决定深入研究它并与各位[分享][2]。 + +### 获得支持 + +为了建立公司强大的企业文化,有人会反对改变,并且从幕后打压任何改变的提议。他们希望每个人都待在那个舒适的洞穴里。例如,当我第一次接触到海外销售培训,我受到了一些关键人物的严厉阻挠。他们迫使其他人相信某个东京人做不了销售培训——只要基本的产品培训就行了。 + +尽管我最终解决了这个问题,但我那时候真的不知道该怎么办。所以,我开始研究顾问们在改变公司里抗拒改变的人的想法这个问题上该如何给出建议。从学者 [Laurence Haughton][3] 的研究中,我发现一般对于改变的提议,组织中 83% 的人最开始不会支持你。大约 17% _会_从一开始就支持你,但是只要看到一个实验案例成功之后,他们觉得这个主意安全可行了,60% 的人会支持你。最后,有部分人会反对任何改变,无论它有多棒。 + +我研究的步骤: + +* 从试验项目开始 +* 开导洞穴人 +* 快速跟进 +* 开导洞穴首领 +* 全局展开 + +### 1、 从试验项目开始 + +找到高价值且成功率较高的项目——而不是大的、成本高的、周期长的、全局的行动。然后,找到能看到项目价值、理解它的价值并能为之奋斗的关键人物。这些人不应该只是“老好人”或者“朋友”;他们必须相信项目的目标而且拥有推进项目的能力或经验。不要急于求成。只要足够支持你研究并保持进度即可。 + +个人而言,我在新加坡的一个小型车辆代理商那里举办了自己的第一场销售研讨会。虽然并不是特别成功,但足以让人们开始讨论销售训练会达到怎样的效果。那时候的我困在洞穴里(那是一份我不想做的工作)。这个试验销售训练是我走出困境的蓝图。 + +### 2、 开导洞穴人 + +洞穴(CAVE)实际上是我从 Laurence Haughton 那里听来的缩略词。它代表着 Citizens Against Virtually Everything。(LCTT 译注,此处一语双关前文提及的洞穴。) + +你得辨别这些人,因为他们会暗地里阻挠项目的进展,特别是早期脆弱的时候。他们容易黑化:总是消极。他们频繁使用“但是”、“如果”和“为什么”,只是想推脱你。他们询问轻易不可得的细节信息。他们花费过多的时间在问题上,而不是寻找解决方案。他们认为每个失败都是一个趋势。他们总是对人而不是对事。他们作出反对建议的陈述却又不能简单确认。 + +避开洞穴人;不要让他们太早加入项目的讨论。他们固守成见,因为他们看不到改变所具有的价值。他们安居于洞穴,所以试着让他们去做些其他事。你应该找出我上面提到那 17% 的人群中的关键人物,那些想要改变的人,并且跟他们开一个非常隐秘的准备会。 + +我在五十铃汽车(股东之一是通用汽车公司)的时候,销售训练项目开始于一个销往世界上其他小国家的合资分销商,主要是非洲、南亚、拉丁美洲和中东。我的个人团队由通用汽车公司雪佛兰的人、五十铃产品经理和分公司的销售计划员工组成。隔绝其他任何人于这个圈子之外。 + +### 3、 快速跟进 + +洞穴人总是慢吞吞的,那么你就迅速行动起来。如果你在他们参与之前就有了小成就的经历,他们对你团队产生消极影响的能力将大大减弱——你要在他们提出之前就解决他们必然反对的问题。再一次,选择一个成功率高的试验项目,很快能出结果的。然后宣传成功,就像广告上的加粗标题。 + +当我在新加坡研讨会上所言开始流传时,其他地区开始意识到销售训练的好处。仅在新加坡研讨会之后,我就被派到马来西亚开展了四次以上。 + +### 4、 开导洞穴首领 + +只要你取得了第一个小项目的成功,就针对能影响洞穴首领的关键人物推荐项目。让团队继续该项目以告诉关键人物成功的经历。一线人员甚至顾客也能提供有力的证明。 洞穴管理者往往只着眼于销量和收益,那么就宣扬项目在降低开支、减少浪费和增加销量方面的价值。 + +自新加坡的第一次研讨会及之后,我向直接掌握了五十铃销售渠道的前线销售部门员工和通用汽车真正想看到进展的人极力宣传他们的成功。当他们接受了之后,他们会向上级提出培训请求并让其看到分公司销量的提升。 + +### 5、 全局展开 + +一旦一把手站在了自己这边,立马向整个组织宣告成功的试验项目。讨论项目的扩展。 + +用上面的方法,在 21 年的职业生涯中,我在世界各地超过 60 个国家举办了研讨会。我确实走出了洞穴——并且真的看到了广阔的世界。 + +(题图:opensource.com) + +-------------------------------------------------------------------------------- + +作者简介: + +Ron McFarland - Ron McFarland 已在日本工作 40 年,从事国际销售、销售管理和在世界范围内扩展销售业务 30 载有余。他曾去过或就职于 80 多个国家。在过去的 14 年里, Ron 为总部位于东京的日本硬件切割厂在美国和欧洲各地建立分销商。 + +-------------------------------------------------------------------------------- + +via: https://opensource.com/open-organization/17/1/escape-the-cave + +作者:[Ron McFarland][a] +译者:[XYenChi](https://github.com/XYenChi) +校对:[wxy](https://github.com/wxy) + +本文由 [LCTT](https://github.com/LCTT/TranslateProject) 原创编译,[Linux中国](https://linux.cn/) 荣誉推出 + +[a]:https://opensource.com/users/ron-mcfarland +[1]:https://opensource.com/open-organization/17/1/escape-the-cave?rate=dBJIKVJy720uFj0PCfa1JXDZKkMwozxV8TB2qJnoghM +[2]:http://www.slideshare.net/RonMcFarland1/creating-change-58994683 +[3]:http://www.laurencehaughton.com/ +[4]:https://opensource.com/user/68021/feed +[5]:https://opensource.com/open-organization/17/1/escape-the-cave#comments +[6]:https://opensource.com/users/ron-mcfarland diff --git a/published/20170228 How to create a snap for timg with snapcraft on Ubuntu.md b/published/201710/20170228 How to create a snap for timg with snapcraft on Ubuntu.md similarity index 100% rename from published/20170228 How to create a snap for timg with snapcraft on Ubuntu.md rename to published/201710/20170228 How to create a snap for timg with snapcraft on Ubuntu.md diff --git a/published/201710/20170310 Why DevOps is the end of security as we know it.md b/published/201710/20170310 Why DevOps is the end of security as we know it.md new file mode 100644 index 0000000000..ad7f437867 --- /dev/null +++ b/published/201710/20170310 Why DevOps is the end of security as we know it.md @@ -0,0 +1,66 @@ +为什么 DevOps 如我们所知道的那样,是安全的终结 +========== + +![](https://techbeacon.com/sites/default/files/styles/article_hero_image/public/field/image/rugged-devops-end-of-security.jpg?itok=Gp1xxSMK) + +安全难以推行。在企业管理者迫使开发团队尽快发布程序的大环境下,很难说服他们花费有限的时间来修补安全漏洞。但是鉴于所有网络攻击中有 84% 发生在应用层,作为一个组织是无法承担其开发团队不包括安全性带来的后果。 + +DevOps 的崛起为许多安全负责人带来了困境。Sonatype 的前 CTO [Josh Corman][2] 说:“这是对安全的威胁,但这也是让安全变得更好的机会。” Corman 是一个坚定的[将安全和 DevOps 实践整合起来创建 “坚固的 DevOps”][3]的倡导者。_Business Insights_ 与 Corman 谈论了安全和 DevOps 共同的价值,以及这些共同价值如何帮助组织更少地受到中断和攻击的影响。 + +### 安全和 DevOps 实践如何互惠互利? + +**Josh Corman:** 一个主要的例子是 DevOps 团队对所有可测量的东西进行检测的倾向。安全性一直在寻找更多的情报和遥测。你可以获取许多 DevOps 团队正在测量的信息,并将这些信息输入到你的日志管理或 SIEM (安全信息和事件管理系统)。 + +一个 OODA 循环(观察observe定向orient决定decide行为act)的前提是有足够普遍的眼睛和耳朵,以注意到窃窃私语和回声。DevOps 为你提供无处不在的仪器。 + +### 他们有分享其他文化观点吗? + +**JC:** “严肃对待你的代码”是一个共同的价值观。例如,由 Netflix 编写的软件工具 Chaos Monkey 是 DevOps 团队的分水岭。它是为了测试亚马逊网络服务的弹性和可恢复性而创建的,Chaos Monkey 使得 Netflix 团队更加强大,更容易为中断做好准备。 + +所以现在有个想法是我们的系统需要测试,因此,James Wickett 和我及其他人决定做一个邪恶的、带有攻击性的 Chaos Monkey,这就是 GAUNTLT 项目的来由。它基本上是一堆安全测试, 可以在 DevOps 周期和 DevOps 工具链中使用。它也有非常适合 DevOps 的API。 + +### 企业安全和 DevOps 价值在哪里相交? + +**JC:** 这两个团队都认为复杂性是一切事情的敌人。例如,[安全人员和 Rugged DevOps 人员][4]实际上可以说:“看,我们在我们的项目中使用了 11 个日志框架 - 也许我们不需要那么多,也许攻击面和复杂性可能会让我们受到伤害或者损害产品的质量或可用性。” + +复杂性往往是许多事情的敌人。通常情况下,你不会很难说服 DevOps 团队在架构层面使用更好的建筑材料:使用最新的、最不易受攻击的版本,并使用较少的组件。 + +### “更好的建筑材料”是什么意思? + +**JC:** 我是世界上最大的开源仓库的保管人,所以我能看到他们在使用哪些版本,里面有哪些漏洞,何时他们没有修复漏洞,以及等了多久。例如,某些日志记录框架从不会修复任何错误。其中一些会在 90 天内修复了大部分的安全漏洞。人们越来越多地遭到攻击,因为他们使用了一个毫无安全的框架。 + +除此之外,即使你不知道日志框架的质量,拥有 11 个不同的框架会变得非常笨重、出现 bug,还有额外的工作和复杂性。你暴露在漏洞中的风险是非常大的。你想把时间花在修复大量的缺陷上,还是在制造下一个大的破坏性的事情上? + +[Rugged DevOps 的关键是软件供应链管理][5],其中包含三个原则:使用更少和更好的供应商、使用这些供应商的最高质量的部分、并跟踪这些部分,以便在发生错误时,你可以有一个及时和敏捷的响应。 + +### 所以变更管理也很重要。 + +**JC:** 是的,这是另一个共同的价值。我发现,当一家公司想要执行诸如异常检测或净流量分析等安全测试时,他们需要知道“正常”的样子。让人们失误的许多基本事情与仓库和补丁管理有关。 + +我在 _Verizon 数据泄露调查报告_中看到,追踪去年被成功利用的漏洞后,其中 97% 归结为 10 个 CVE(常见漏洞和风险),而这 10 个已经被修复了十多年。所以,我们羞于谈论高级间谍活动。我们没有做基本的补丁工作。现在,我不是说如果你修复这 10 个CVE,那么你就没有被利用,而是这占据了人们实际失误的最大份额。 + +[DevOps 自动化工具][6]的好处是它们已经成为一个意外的变更管理数据库。其真实反应了谁在哪里什么时候做了变更。这是一个巨大的胜利,因为我们经常对安全性有最大影响的因素无法控制。你承受了 CIO 和 CTO 做出的选择的后果。随着 IT 通过自动化变得更加严格和可重复,你可以减少人为错误的机会,并且哪里发生了变化更加可追溯。 + +### 你认为什么是最重要的共同价值? + +**JC:** DevOps 涉及到过程和工具链,但我认为定义这种属性的是文化,特别是同感。 DevOps 有用是因为开发人员和运维团队能够更好地了解彼此,并做出更明智的决策。不是在解决孤岛中的问题,而是为了活动流程和目标解决。如果你向 DevOps 的团队展示安全如何能使他们变得更好,那么作为回馈他们往往会问:“那么,我们是否有任何选择让你的生活更轻松?”因为他们通常不知道他们做的 X、Y 或 Z 的选择使它无法包含安全性。 + +对于安全团队,驱动价值的方法之一是在寻求帮助之前变得更有所帮助,在我们告诉 DevOps 团队要做什么之前提供定性和定量的价值。你必须获得 DevOps 团队的信任,并获得发挥的权利,然后才能得到回报。它通常比你想象的快很多。 + +-------------------------------------------------------------------------------- + +via: https://techbeacon.com/why-devops-end-security-we-know-it + +作者:[Mike Barton][a] +译者:[geekpi](https://github.com/geekpi) +校对:[wxy](https://github.com/wxy) + +本文由 [LCTT](https://github.com/LCTT/TranslateProject) 原创编译,[Linux中国](https://linux.cn/) 荣誉推出 + +[a]:https://twitter.com/intent/follow?original_referer=https%3A%2F%2Ftechbeacon.com%2Fwhy-devops-end-security-we-know-it%3Fimm_mid%3D0ee8c5%26cmp%3Dem-webops-na-na-newsltr_20170310&ref_src=twsrc%5Etfw®ion=follow_link&screen_name=mikebarton&tw_p=followbutton +[1]:https://techbeacon.com/resources/application-security-devops-true-state?utm_source=tb&utm_medium=article&utm_campaign=inline-cta +[2]:https://twitter.com/joshcorman +[3]:https://techbeacon.com/want-rugged-devops-team-your-release-security-engineers +[4]:https://techbeacon.com/rugged-devops-rsa-6-takeaways-security-ops-pros +[5]:https://techbeacon.com/josh-corman-security-devops-how-shared-team-values-can-reduce-threats +[6]:https://techbeacon.com/devops-automation-best-practices-how-much-too-much diff --git a/published/20170312 OpenGL Go Tutorial Part 1.md b/published/201710/20170312 OpenGL Go Tutorial Part 1.md similarity index 100% rename from published/20170312 OpenGL Go Tutorial Part 1.md rename to published/201710/20170312 OpenGL Go Tutorial Part 1.md diff --git a/published/20170312 OpenGL Go Tutorial Part 2 Drawing the Game Board.md b/published/201710/20170312 OpenGL Go Tutorial Part 2 Drawing the Game Board.md similarity index 100% rename from published/20170312 OpenGL Go Tutorial Part 2 Drawing the Game Board.md rename to published/201710/20170312 OpenGL Go Tutorial Part 2 Drawing the Game Board.md diff --git a/translated/tech/20170312 OpenGL Go Tutorial Part 3 Implementing the Game.md b/published/201710/20170312 OpenGL Go Tutorial Part 3 Implementing the Game.md similarity index 66% rename from translated/tech/20170312 OpenGL Go Tutorial Part 3 Implementing the Game.md rename to published/201710/20170312 OpenGL Go Tutorial Part 3 Implementing the Game.md index 664380f5c4..4c5175cda1 100644 --- a/translated/tech/20170312 OpenGL Go Tutorial Part 3 Implementing the Game.md +++ b/published/201710/20170312 OpenGL Go Tutorial Part 3 Implementing the Game.md @@ -1,21 +1,23 @@ -OpenGL 与 Go 教程第三节:实现游戏 +OpenGL 与 Go 教程(三)实现游戏 ============================================================ -[第一节: Hello, OpenGL][8]  |  [第二节: 绘制游戏面板][9]  |  [第三节:实现游戏功能][10] +- [第一节: Hello, OpenGL][8] +- [第二节: 绘制游戏面板][9] +- [第三节:实现游戏功能][10] -该教程的完整源代码可以从 [GitHub][11] 上获得。 +该教程的完整源代码可以从 [GitHub][11] 上找到。 欢迎回到《OpenGL 与 Go 教程》!如果你还没有看过 [第一节][12] 和 [第二节][13],那就要回过头去看一看。 -到目前为止,你应该懂得如何创建网格系统以及创建代表方格中每一个单元的格子阵列。现在可以开始把网格当作游戏面板实现《Conway's Game of Life》。 +到目前为止,你应该懂得如何创建网格系统以及创建代表方格中每一个单元的格子阵列。现在可以开始把网格当作游戏面板实现康威生命游戏Conway's Game of Life。 开始吧! -### 实现 《Conway’s Game》 +### 实现康威生命游戏 -《Conway's Game》的其中一个要点是所有 cell 必须同时基于当前 cell 在面板中的状态确定下一个 cell 的状态。也就是说如果 Cell (X=3,Y=4)在计算过程中状态发生了改变,那么邻近的 cell (X=4,Y=4)必须基于(X=3,T=4)的状态决定自己的状态变化,而不是基于自己现在的状态。简单的讲,这意味着我们必须遍历 cell ,确定下一个 cell 的状态,在绘制之前,不改变他们的当前状态,然后在下一次循环中我们将新状态应用到游戏里,依此循环往复。 +康威生命游戏的其中一个要点是所有细胞cell必须同时基于当前细胞在面板中的状态确定下一个细胞的状态。也就是说如果细胞 `(X=3,Y=4)` 在计算过程中状态发生了改变,那么邻近的细胞 `(X=4,Y=4)` 必须基于 `(X=3,Y=4)` 的状态决定自己的状态变化,而不是基于自己现在的状态。简单的讲,这意味着我们必须遍历细胞,确定下一个细胞的状态,而在绘制之前不改变他们的当前状态,然后在下一次循环中我们将新状态应用到游戏里,依此循环往复。 -为了完成这个功能,我们需要在 cell 结构体中添加两个布尔型变量: +为了完成这个功能,我们需要在 `cell` 结构体中添加两个布尔型变量: ``` type cell struct { @@ -29,6 +31,8 @@ type cell struct { } ``` +这里我们添加了 `alive` 和 `aliveNext`,前一个是细胞当前的专题,后一个是经过计算后下一回合的状态。 + 现在添加两个函数,我们会用它们来确定 cell 的状态: ``` @@ -39,22 +43,22 @@ func (c *cell) checkState(cells [][]*cell) { liveCount := c.liveNeighbors(cells) if c.alive { - // 1\. 当任何一个存活的 cell 的附近少于 2 个存活的 cell 时,该 cell 将会消亡,就像人口过少所导致的结果一样 + // 1. 当任何一个存活的 cell 的附近少于 2 个存活的 cell 时,该 cell 将会消亡,就像人口过少所导致的结果一样 if liveCount < 2 { c.aliveNext = false } - // 2\. 当任何一个存活的 cell 的附近有 2 至 3 个存活的 cell 时,该 cell 在下一代中仍然存活。 + // 2. 当任何一个存活的 cell 的附近有 2 至 3 个存活的 cell 时,该 cell 在下一代中仍然存活。 if liveCount == 2 || liveCount == 3 { c.aliveNext = true } - // 3\. 当任何一个存活的 cell 的附近多于 3 个存活的 cell 时,该 cell 将会消亡,就像人口过多所导致的结果一样 + // 3. 当任何一个存活的 cell 的附近多于 3 个存活的 cell 时,该 cell 将会消亡,就像人口过多所导致的结果一样 if liveCount > 3 { c.aliveNext = false } } else { - // 4\. 任何一个消亡的 cell 附近刚好有 3 个存活的 cell,该 cell 会变为存活的状态,就像重生一样。 + // 4. 任何一个消亡的 cell 附近刚好有 3 个存活的 cell,该 cell 会变为存活的状态,就像重生一样。 if liveCount == 3 { c.aliveNext = true } @@ -95,9 +99,11 @@ func (c *cell) liveNeighbors(cells [][]*cell) int { } ``` -更加值得注意的是 liveNeighbors 函数里在返回地方,我们返回的是当前处于存活状态的 cell 的邻居个数。我们定义了一个叫做 add 的内嵌函数,它会对 X 和 Y 坐标做一些重复性的验证。它所做的事情是检查我们传递的数字是否超出了范围——比如说,如果 cell(X=0,Y=5)想要验证它左边的 cell,它就得验证面板另一边的 cell(X=9,Y=5),Y 轴与之类似。 +在 `checkState` 中我们设置当前状态(`alive`) 等于我们最近迭代结果(`aliveNext`)。接下来我们计数邻居数量,并根据游戏的规则来决定 `aliveNext` 状态。该规则是比较清晰的,而且我们在上面的代码当中也有说明,所以这里不再赘述。 -在 add 内嵌函数后面,我们给当前 cell 附近的八个 cell 分别调用 add 函数,示意如下: +更加值得注意的是 `liveNeighbors` 函数里,我们返回的是当前处于存活(`alive`)状态的细胞的邻居个数。我们定义了一个叫做 `add` 的内嵌函数,它会对 `X` 和 `Y` 坐标做一些重复性的验证。它所做的事情是检查我们传递的数字是否超出了范围——比如说,如果细胞 `(X=0,Y=5)` 想要验证它左边的细胞,它就得验证面板另一边的细胞 `(X=9,Y=5)`,Y 轴与之类似。 + +在 `add` 内嵌函数后面,我们给当前细胞附近的八个细胞分别调用 `add` 函数,示意如下: ``` [ @@ -109,9 +115,9 @@ func (c *cell) liveNeighbors(cells [][]*cell) int { ] ``` -在该示意中,每一个叫做 N 的 cell 是与 C 相邻的 cell。 +在该示意中,每一个叫做 N 的细胞是 C 的邻居。 -现在是我们的主函数,在我们执行循环核心游戏的地方,调用每个 cell 的 checkState 函数进行绘制: +现在是我们的 `main` 函数,这里我们执行核心游戏循环,调用每个细胞的 `checkState` 函数进行绘制: ``` func main() { @@ -129,6 +135,8 @@ func main() { } ``` +现在我们的游戏逻辑全都设置好了,我们需要修改细胞绘制函数来跳过绘制不存活的细胞: + ``` func (c *cell) draw() { if !c.alive { @@ -140,7 +148,10 @@ func (c *cell) draw() { } ``` -现在完善这个函数。回到 makeCells 函数,我们用 0.0 到 1.0 之间的一个随机数来设置游戏的初始状态。我们会定义一个大小为 0.15 的常量阈值,也就是说每个 cell 都有 15% 的几率处于存活状态。 +如果我们现在运行这个游戏,你将看到一个纯黑的屏幕,而不是我们辛苦工作后应该看到生命模拟。为什么呢?其实这正是模拟在工作。因为我们没有活着的细胞,所以就一个都不会绘制出来。 + + +现在完善这个函数。回到 `makeCells` 函数,我们用 `0.0` 到 `1.0` 之间的一个随机数来设置游戏的初始状态。我们会定义一个大小为 `0.15` 的常量阈值,也就是说每个细胞都有 15% 的几率处于存活状态。 ``` import ( @@ -174,11 +185,13 @@ func makeCells() [][]*cell { } ``` -接下来在循环中,在用 newCell 函数创造一个新的 cell 时,我们根据随机数的大小设置它的存活状态,随机数在 0.0 到 1.0 之间,如果比阈值(0.15)小,就是存活状态。再次强调,这意味着每个 cell 在开始时都有 15% 的几率是存活的。你可以修改数值大小,增加或者减少当前游戏中存活的 cell。我们还把 aliveNext 设成 alive 状态,否则在第一次迭代之后我们会发现一大片 cell 消亡了,这是因为 aliveNext 将永远是 false。 +我们首先增加两个引入:随机(`math/rand`)和时间(`time`),并定义我们的常量阈值。然后在 `makeCells` 中我们使用当前时间作为随机种子,给每个游戏一个独特的起始状态。你也可也指定一个特定的种子值,来始终得到一个相同的游戏,这在你想重放某个有趣的模拟时很有用。 -现在接着往下看,运行它,你很有可能看到 cell 们一闪而过,但你却无法理解这是为什么。原因可能在于你的电脑太快了,在你能够看清楚之前就运行了(甚至完成了)模拟过程。 +接下来在循环中,在用 `newCell` 函数创造一个新的细胞时,我们根据随机浮点数的大小设置它的存活状态,随机数在 `0.0` 到 `1.0` 之间,如果比阈值(`0.15`)小,就是存活状态。再次强调,这意味着每个细胞在开始时都有 15% 的几率是存活的。你可以修改数值大小,增加或者减少当前游戏中存活的细胞。我们还把 `aliveNext` 设成 `alive` 状态,否则在第一次迭代之后我们会发现一大片细胞消亡了,这是因为 `aliveNext` 将永远是 `false`。 -降低游戏速度,在主循环中引入一个 frames-per-second 限制: +现在继续运行它,你很有可能看到细胞们一闪而过,但你却无法理解这是为什么。原因可能在于你的电脑太快了,在你能够看清楚之前就运行了(甚至完成了)模拟过程。 + +让我们降低游戏速度,在主循环中引入一个帧率(FPS)限制: ``` const ( @@ -223,7 +236,7 @@ const ( ) ``` - ![《OpenGL 和 Golang 教程》 中的 “Conway's Game of Life” - 示例游戏](https://kylewbanks.com/images/post/golang-opengl-conway-1.gif) + ![ “Conway's Game of Life” - 示例游戏](https://kylewbanks.com/images/post/golang-opengl-conway-1.gif) 试着修改常量,看看它们是怎么影响模拟过程的 —— 这是你用 Go 语言写的第一个 OpenGL 程序,很酷吧? @@ -231,20 +244,18 @@ const ( 这是《OpenGL 与 Go 教程》的最后一节,但是这不意味着到此而止。这里有些新的挑战,能够增进你对 OpenGL (以及 Go)的理解。 -1. 给每个 cell 一种不同的颜色。 -2. 让用户能够通过命令行参数指定格子尺寸,帧率,种子和阈值。在 GitHub 上的 [github.com/KyleBanks/conways-gol][4] 里你可以看到一个已经实现的程序。 +1. 给每个细胞一种不同的颜色。 +2. 让用户能够通过命令行参数指定格子尺寸、帧率、种子和阈值。在 GitHub 上的 [github.com/KyleBanks/conways-gol][4] 里你可以看到一个已经实现的程序。 3. 把格子的形状变成其它更有意思的,比如六边形。 -4. 用颜色表示 cell 的状态 —— 比如,在第一帧把存活状态的格子设成绿色,如果它们存活了超过三帧的时间,就变成黄色。 -5. 如果模拟过程结束了,就自动关闭窗口,也就是说所有 cell 都消亡了,或者是最后两帧里没有格子的状态有改变。 +4. 用颜色表示细胞的状态 —— 比如,在第一帧把存活状态的格子设成绿色,如果它们存活了超过三帧的时间,就变成黄色。 +5. 如果模拟过程结束了,就自动关闭窗口,也就是说所有细胞都消亡了,或者是最后两帧里没有格子的状态有改变。 6. 将着色器源代码放到单独的文件中,而不是把它们用字符串的形式放在 Go 的源代码中。 ### 总结 希望这篇教程对想要入门 OpenGL (或者是 Go)的人有所帮助!这很有趣,因此我也希望理解学习它也很有趣。 -正如我所说的,OpenGL 可能是非常恐怖的,但只要你开始着手了就不会太差。你只用制定一个个可达成的小目标,然后享受每一次成功,因为尽管 OpenGL 不会总像它看上去的那么难,但也肯定有些难懂的东西。我发现,当遇到一个难于用 go-gl 方式理解的 OpenGL 问题时,你总是可以参考一下在网上更流行的当作教程的 C 语言代码,这很有用。通常 C 语言和 Go 语言的唯一区别是在 Go 中,gl 的前缀是 gl. 而不是 GL_。这极大地增加了你的绘制知识! - -[第一节: Hello, OpenGL][14]  |  [第二节: 绘制游戏面板][15]  |  [第三节:实现游戏功能][16] +正如我所说的,OpenGL 可能是非常恐怖的,但只要你开始着手了就不会太差。你只用制定一个个可达成的小目标,然后享受每一次成功,因为尽管 OpenGL 不会总像它看上去的那么难,但也肯定有些难懂的东西。我发现,当遇到一个难于理解用 go-gl 生成的代码的 OpenGL 问题时,你总是可以参考一下在网上更流行的当作教程的 C 语言代码,这很有用。通常 C 语言和 Go 语言的唯一区别是在 Go 中,gl 函数的前缀是 `gl.` 而不是 `gl`,常量的前缀是 `gl` 而不是 `GL_`。这可以极大地增加了你的绘制知识! 该教程的完整源代码可从 [GitHub][17] 上获得。 @@ -419,22 +430,22 @@ func (c *cell) checkState(cells [][]*cell) { liveCount := c.liveNeighbors(cells) if c.alive { - // 1\. 当任何一个存活的 cell 的附近少于 2 个存活的 cell 时,该 cell 将会消亡,就像人口过少所导致的结果一样 + // 1. 当任何一个存活的 cell 的附近少于 2 个存活的 cell 时,该 cell 将会消亡,就像人口过少所导致的结果一样 if liveCount < 2 { c.aliveNext = false } - // 2\. 当任何一个存活的 cell 的附近有 2 至 3 个存活的 cell 时,该 cell 在下一代中仍然存活。 + // 2. 当任何一个存活的 cell 的附近有 2 至 3 个存活的 cell 时,该 cell 在下一代中仍然存活。 if liveCount == 2 || liveCount == 3 { c.aliveNext = true } - // 3\. 当任何一个存活的 cell 的附近多于 3 个存活的 cell 时,该 cell 将会消亡,就像人口过多所导致的结果一样 + // 3. 当任何一个存活的 cell 的附近多于 3 个存活的 cell 时,该 cell 将会消亡,就像人口过多所导致的结果一样 if liveCount > 3 { c.aliveNext = false } } else { - // 4\. 任何一个消亡的 cell 附近刚好有 3 个存活的 cell,该 cell 会变为存活的状态,就像重生一样。 + // 4. 任何一个消亡的 cell 附近刚好有 3 个存活的 cell,该 cell 会变为存活的状态,就像重生一样。 if liveCount == 3 { c.aliveNext = true } @@ -570,9 +581,9 @@ func compileShader(source string, shaderType uint32) (uint32, error) { via: https://kylewbanks.com/blog/tutorial-opengl-with-golang-part-3-implementing-the-game -作者:[kylewbanks ][a] +作者:[kylewbanks][a] 译者:[GitFuture](https://github.com/GitFuture) -校对:[校对者ID](https://github.com/校对者ID) +校对:[wxy](https://github.com/wxy) 本文由 [LCTT](https://github.com/LCTT/TranslateProject) 原创编译,[Linux中国](https://linux.cn/) 荣誉推出 @@ -584,14 +595,14 @@ via: https://kylewbanks.com/blog/tutorial-opengl-with-golang-part-3-implementing [5]:https://kylewbanks.com/category/golang [6]:https://kylewbanks.com/category/opengl [7]:https://twitter.com/kylewbanks -[8]:https://kylewbanks.com/blog/tutorial-opengl-with-golang-part-1-hello-opengl -[9]:https://kylewbanks.com/blog/tutorial-opengl-with-golang-part-2-drawing-the-game-board +[8]:https://linux.cn/article-8933-1.html +[9]:https://linux.cn/article-8937-1.html [10]:https://kylewbanks.com/blog/tutorial-opengl-with-golang-part-3-implementing-the-game [11]:https://github.com/KyleBanks/conways-gol -[12]:https://kylewbanks.com/blog/tutorial-opengl-with-golang-part-1-hello-opengl +[12]:https://linux.cn/article-8933-1.html [13]:https://kylewbanks.com/blog/[Part%202:%20Drawing%20the%20Game%20Board](/blog/tutorial-opengl-with-golang-part-2-drawing-the-game-board) -[14]:https://kylewbanks.com/blog/tutorial-opengl-with-golang-part-1-hello-opengl -[15]:https://kylewbanks.com/blog/tutorial-opengl-with-golang-part-2-drawing-the-game-board +[14]:https://linux.cn/article-8933-1.html +[15]:https://linux.cn/article-8937-1.html [16]:https://kylewbanks.com/blog/tutorial-opengl-with-golang-part-3-implementing-the-game [17]:https://github.com/KyleBanks/conways-gol [18]:https://twitter.com/kylewbanks diff --git a/published/201710/20170403 Introducing Flashback an Internet mocking tool.md b/published/201710/20170403 Introducing Flashback an Internet mocking tool.md new file mode 100644 index 0000000000..accd2f3796 --- /dev/null +++ b/published/201710/20170403 Introducing Flashback an Internet mocking tool.md @@ -0,0 +1,211 @@ +介绍 Flashback,一个互联网模拟工具 +============================================================ + +> Flashback 用于测试目的来模拟 HTTP 和 HTTPS 资源,如 Web 服务和 REST API。 + + ![Introducing Flashback, an Internet mocking tool](https://opensource.com/sites/default/files/styles/image-full-size/public/lead-images/OSDC_Internet_Cables_520x292_0614_RD.png?itok=trjYWg6g "Introducing Flashback, an Internet mocking tool") + +在 LinkedIn,我们经常开发需要与第三方网站交互的 Web 应用程序。我们还采用自动测试,以确保我们的软件在发布到生产环境之前的质量。然而,测试只是在它可靠时才有用。 + +考虑到这一点,有外部依赖关系的测试是有很大的问题的,例如在第三方网站上。这些外部网站可能会没有通知地发生改变、遭受停机,或者由于互联网的不可靠性暂时无法访问。 + +如果我们的一个测试依赖于能够与第三方网站通信,那么任何故障的原因都很难确定。失败可能是因为 LinkedIn 的内部变更、第三方网站的维护人员进行的外部变更,或网络基础设施的问题。你可以想像,与第三方网站的交互可能会有很多失败的原因,因此你可能想要知道,我将如何处理这个问题? + +好消息是有许多互联网模拟工具可以帮助。其中一个是 [Betamax][4]。它通过拦截 Web 应用程序发起的 HTTP 连接,之后进行重放的方式来工作。对于测试,Betamax 可以用以前记录的响应替换 HTTP 上的任何交互,它可以非常可靠地提供这个服务。 + +最初,我们选择在 LinkedIn 的自动化测试中使用 Betamax。它工作得很好,但我们遇到了一些问题: + +* 出于安全考虑,我们的测试环境没有接入互联网。然而,与大多数代理一样,Betamax 需要 Internet 连接才能正常运行。 +* 我们有许多需要使用身份验证协议的情况,例如 OAuth 和 OpenId。其中一些协议需要通过 HTTP 进行复杂的交互。为了模拟它们,我们需要一个复杂的模型来捕获和重放请求。 + +为了应对这些挑战,我们决定基于 Betamax 的思路,构建我们自己的互联网模拟工具,名为 Flashback。我们也很自豪地宣布 Flashback 现在是开源的。 + +### 什么是 Flashback? + +Flashback 用于测试目的来模拟 HTTP 和 HTTPS 资源,如 Web 服务和 [REST][5] API。它记录 HTTP/HTTPS 请求并重放以前记录的 HTTP 事务 - 我们称之为“场景scene”,这样就不需要连接到 Internet 才能完成测试。 + +Flashback 也可以根据请求的部分匹配重放场景。它使用的是“匹配规则”。匹配规则将传入请求与先前记录的请求相关联,然后将其用于生成响应。例如,以下代码片段实现了一个基本匹配规则,其中测试方法“匹配”[此 URL][6]的传入请求。 + +HTTP 请求通常包含 URL、方法、标头和正文。Flashback 允许为这些组件的任意组合定义匹配规则。Flashback 还允许用户向 URL 查询参数,标头和正文添加白名单或黑名单标签。 + +例如,在 OAuth 授权流程中,请求查询参数可能如下所示: + +``` +oauth_consumer_key="jskdjfljsdklfjlsjdfs", +oauth_nonce="ajskldfjalksjdflkajsdlfjasldfja;lsdkj", +oauth_signature="asdfjaklsdjflasjdflkajsdklf", +oauth_signature_method="HMAC-SHA1", +oauth_timestamp="1318622958", +oauth_token="asdjfkasjdlfajsdklfjalsdjfalksdjflajsdlfa", +oauth_version="1.0" +``` + +这些值许多将随着每个请求而改变,因为 OAuth 要求客户端每次为 `oauth_nonce` 生成一个新值。在我们的测试中,我们需要验证 `oauth_consumer_key`、`oauth_signature_method` 和 `oauth_version` 的值,同时确保 `oauth_nonce`、`oauth_signature`、`oauth_timestamp` 和 `oauth_token` 存在于请求中。Flashback 使我们有能力创建我们自己的匹配规则来实现这一目标。此功能允许我们测试随时间变化的数据、签名、令牌等的请求,而客户端没有任何更改。 + +这种灵活的匹配和在不连接互联网的情况下运行的功能是 Flashback 与其他模拟解决方案不同的特性。其他一些显著特点包括: + +* Flashback 是一种跨平台和跨语言解决方案,能够测试 JVM(Java虚拟机)和非 JVM(C++、Python 等)应用程序。 +* Flashback 可以随时生成 SSL/TLS 证书,以模拟 HTTPS 请求的安全通道。 + +### 如何记录 HTTP 事务 + +使用 Flashback 记录 HTTP 事务以便稍后重放是一个比较简单的过程。在我们深入了解流程之前,我们首先列出一些术语: + +* `Scene` :场景存储以前记录的 HTTP 事务 (以 JSON 格式),它可以在以后重放。例如,这里是一个[Flashback 场景][1]示例。 +* `Root Path` :根路径是包含 Flashback 场景数据的目录的文件路径。 +* `Scene Name` :场景名称是给定场景的名称。 +* `Scene Mode` :场景模式是使用场景的模式, 即“录制”或“重放”。 +* `Match Rule` :匹配规则确定传入的客户端请求是否与给定场景的内容匹配的规则。 +* `Flashback Proxy` :Flashback 代理是一个 HTTP 代理,共有录制和重放两种操作模式。 +* `Host` 和 `Port` :代理主机和端口。 + +为了录制场景,你必须向目的地址发出真实的外部请求,然后 HTTPS 请求和响应将使用你指定的匹配规则存储在场景中。在录制时,Flashback 的行为与典型的 MITM(中间人)代理完全相同 - 只有在重放模式下,连接流和数据流仅限于客户端和代理之间。 + +要实际看下 Flashback,让我们创建一个场景,通过执行以下操作捕获与 example.org 的交互: + +1、 取回 Flashback 的源码: + +``` +git clone https://github.com/linkedin/flashback.git +``` + +2、 启动 Flashback 管理服务器: + +``` +./startAdminServer.sh -port 1234 +``` + +3、 注意上面的 Flashback 将在本地端口 5555 上启动录制模式。匹配规则需要完全匹配(匹配 HTTP 正文、标题和 URL)。场景将存储在 `/tmp/test1` 下。 + +4、 Flashback 现在可以记录了,所以用它来代理对 example.org 的请求: + +``` +curl http://www.example.org -x localhost:5555 -X GET +``` + +5、 Flashback 可以(可选)在一个记录中记录多个请求。要完成录制,[关闭 Flashback][8]。 + +6、 要验证已记录的内容,我们可以在输出目录(`/tmp/test1`)中查看场景的内容。它应该[包含以下内容][9]。 + +[在 Java 代码中使用 Flashback][10]也很容易。 + +### 如何重放 HTTP 事务 + +要重放先前存储的场景,请使用与录制时使用的相同的基本设置。唯一的区别是[将“场景模式”设置为上述步骤 3 中的“播放”][11]。 + +验证响应来自场景而不是外部源的一种方法,是在你执行步骤 1 到 6 时临时禁用 Internet 连接。另一种方法是修改场景文件,看看响应是否与文件中的相同。 + +这是 [Java 中的一个例子][12]。 + +### 如何记录并重播 HTTPS 事务 + +使用 Flashback 记录并重放 HTTPS 事务的过程非常类似于 HTTP 事务的过程。但是,需要特别注意用于 HTTPS SSL 组件的安全证书。为了使 Flashback 作为 MITM 代理,必须创建证书颁发机构(CA)证书。在客户端和 Flashback 之间创建安全通道时将使用此证书,并允许 Flashback 检查其代理的 HTTPS 请求中的数据。然后将此证书存储为受信任的源,以便客户端在进行调用时能够对 Flashback 进行身份验证。有关如何创建证书的说明,有很多[类似这样][13]的资源是非常有帮助的。大多数公司都有自己的管理和获取证书的内部策略 - 请务必用你们自己的方法。 + +这里值得一提的是,Flashback 仅用于测试目的。你可以随时随地将 Flashback 与你的服务集成在一起,但需要注意的是,Flashback 的记录功能将需要存储所有的数据,然后在重放模式下使用它。我们建议你特别注意确保不会无意中记录或存储敏感成员数据。任何可能违反贵公司数据保护或隐私政策的行为都是你的责任。 + +一旦涉及安全证书,HTTP 和 HTTPS 之间在记录设置方面的唯一区别是添加了一些其他参数。 + +* `RootCertificateInputStream`: 表示 CA 证书文件路径或流。 +* `RootCertificatePassphrase`: 为 CA 证书创建的密码。 +* `CertificateAuthority`: CA 证书的属性 + +[查看 Flashback 中用于记录 HTTPS 事务的代码][14],它包括上述条目。 + +用 Flashback 重放 HTTPS 事务的过程与录制相同。唯一的区别是场景模式设置为“播放”。这在[此代码][15]中演示。 + +### 支持动态修改 + +为了测试灵活性,Flashback 允许你动态地更改场景和匹配规则。动态更改场景允许使用不同的响应(如 `success`、`time_out`、`rate_limit` 等)测试相同的请求。[场景更改][16]仅适用于我们已经 POST 更新外部资源的场景。以下图为例。 + + ![Scenarios where we have POSTed data to update the external resource.](https://opensource.com/sites/default/files/changingscenes.jpg "Scenarios where we have POSTed data to update the external resource.") + +能够动态[更改匹配规则][17]可以使我们测试复杂的场景。例如,我们有一个使用情况,要求我们测试 Twitter 的公共和私有资源的 HTTP 调用。对于公共资源,HTTP 请求是不变的,所以我们可以使用 “MatchAll” 规则。然而,对于私人资源,我们需要使用 OAuth 消费者密码和 OAuth 访问令牌来签名请求。这些请求包含大量具有不可预测值的参数,因此静态 MatchAll 规则将无法正常工作。 + +### 使用案例 + +在 LinkedIn,Flashback 主要用于在集成测试中模拟不同的互联网提供商,如下图所示。第一张图展示了 LinkedIn 生产数据中心内的一个内部服务,通过代理层,与互联网提供商(如 Google)进行交互。我们想在测试环境中测试这个内部服务。 + + ![Testing this internal service in a testing environment.](https://opensource.com/sites/default/files/testingenvironment.jpg "Testing this internal service in a testing environment.") + +第二和第三张图表展示了我们如何在不同的环境中录制和重放场景。记录发生在我们的开发环境中,用户在代理启动的同一端口上启动 Flashback。从内部服务到提供商的所有外部请求将通过 Flashback 而不是我们的代理层。在必要场景得到记录后,我们可以将其部署到我们的测试环境中。 + + ![After the necessary scenes get recorded, we can deploy them to our test environment.](https://opensource.com/sites/default/files/testenvironmentimage2.jpg "After the necessary scenes get recorded, we can deploy them to our test environment.") + +在测试环境(隔离并且没有 Internet 访问)中,Flashback 在与开发环境相同的端口上启动。所有 HTTP 请求仍然来自内部服务,但响应将来自 Flashback 而不是 Internet 提供商。 + + ![Responses will come from Flashback instead of the Internet providers.](https://opensource.com/sites/default/files/flashbackresponsesimage.jpg "Responses will come from Flashback instead of the Internet providers.") + +### 未来方向 + +我们希望将来可以支持非 HTTP 协议(如 FTP 或 JDBC),甚至可以让用户使用 MITM 代理框架来自行注入自己的定制协议。我们将继续改进 Flashback 设置 API,使其更容易支持非 Java 语言。 + +### 现在为一个开源项目 + +我们很幸运能够在 GTAC 2015 上发布 Flashback。在展会上,有几名观众询问是否将 Flashback 作为开源项目发布,以便他们可以将其用于自己的测试工作。 + +### Google TechTalks:GATC 2015 - 模拟互联网 + + + +我们很高兴地宣布,Flashback 现在以 BSD 两句版许可证开源。要开始使用,请访问 [Flashback GitHub 仓库][18]。 + + _该文原始发表在[LinkedIn 工程博客上][2]。获得转载许可_ + +### 致谢 + +Flashback 由 [Shangshang Feng][19]、[Yabin Kang][20] 和 [Dan Vinegrad][21] 创建,并受到 [Betamax][22] 启发。特别感谢 [Hwansoo Lee][23]、[Eran Leshem][24]、[Kunal Kandekar][25]、[Keith Dsouza][26] 和 [Kang Wang][27] 帮助审阅代码。同样感谢我们的管理层 - [Byron Ma][28]、[Yaz Shimizu][29]、[Yuliya Averbukh][30]、[Christopher Hazlett][31] 和 [Brandon Duncan][32] - 感谢他们在开发和开源 Flashback 中的支持。 + + +(题图:Opensource.com) + +-------------------------------------------------------------------------------- + +作者简介: + +Shangshang Feng - Shangshang 是 LinkedIn 纽约市办公室的高级软件工程师。在 LinkedIn 他从事了三年半的网关平台工作。在加入 LinkedIn 之前,他曾在 Thomson Reuters 和 ViewTrade 证券的基础设施团队工作。 + +--------- + +via: https://opensource.com/article/17/4/flashback-internet-mocking-tool + +作者:[Shangshang Feng][a] +译者:[geekpi](https://github.com/geekpi) +校对:[jasminepeng](https://github.com/jasminepeng) + +本文由 [LCTT](https://github.com/LCTT/TranslateProject) 原创编译,[Linux中国](https://linux.cn/) 荣誉推出 + +[a]:https://opensource.com/users/shangshangfeng +[1]:https://gist.github.com/anonymous/17d226050d8a9b79746a78eda9292382 +[2]:https://engineering.linkedin.com/blog/2017/03/flashback-mocking-tool +[3]:https://opensource.com/article/17/4/flashback-internet-mocking-tool?rate=Jwt7-vq6jP9kS7gOT6f6vgwVlZupbyzWsVXX41ikmGk +[4]:https://github.com/betamaxteam/betamax +[5]:https://en.wikipedia.org/wiki/Representational_state_transfer +[6]:https://gist.github.com/anonymous/91637854364287b38897c0970aad7451 +[7]:https://gist.github.com/anonymous/2f5271191edca93cd2e03ce34d1c2b62 +[8]:https://gist.github.com/anonymous/f899ebe7c4246904bc764b4e1b93c783 +[9]:https://gist.github.com/sf1152/c91d6d62518fe62cc87157c9ce0e60cf +[10]:https://gist.github.com/anonymous/fdd972f1dfc7363f4f683a825879ce19 +[11]:https://gist.github.com/anonymous/ae1c519a974c3bc7de2a925254b6550e +[12]:https://gist.github.com/anonymous/edcc1d60847d51b159c8fd8a8d0a5f8b +[13]:https://jamielinux.com/docs/openssl-certificate-authority/introduction.html +[14]:https://gist.github.com/anonymous/091d13179377c765f63d7bf4275acc11 +[15]:https://gist.github.com/anonymous/ec6a0fd07aab63b7369bf8fde69c1f16 +[16]:https://gist.github.com/anonymous/1f1660280acb41277fbe2c257bab2217 +[17]:https://gist.github.com/anonymous/0683c43f31bd916b76aff348ff87f51b +[18]:https://github.com/linkedin/flashback +[19]:https://www.linkedin.com/in/shangshangfeng +[20]:https://www.linkedin.com/in/benykang +[21]:https://www.linkedin.com/in/danvinegrad/ +[22]:https://github.com/betamaxteam/betamax +[23]:https://www.linkedin.com/in/hwansoo/ +[24]:https://www.linkedin.com/in/eranl/ +[25]:https://www.linkedin.com/in/kunalkandekar/ +[26]:https://www.linkedin.com/in/dsouzakeith/ +[27]:https://www.linkedin.com/in/kang-wang-44960b4/ +[28]:https://www.linkedin.com/in/byronma/ +[29]:https://www.linkedin.com/in/yazshimizu/ +[30]:https://www.linkedin.com/in/yuliya-averbukh-818a41/ +[31]:https://www.linkedin.com/in/chazlett/ +[32]:https://www.linkedin.com/in/dudcat/ +[33]:https://opensource.com/user/125361/feed +[34]:https://opensource.com/users/shangshangfeng diff --git a/published/201710/20170421 A Window Into the Linux Desktop.md b/published/201710/20170421 A Window Into the Linux Desktop.md new file mode 100644 index 0000000000..6a3d50f3f0 --- /dev/null +++ b/published/201710/20170421 A Window Into the Linux Desktop.md @@ -0,0 +1,98 @@ +进入 Linux 桌面之窗 +============================================================ + +![linux-desktop](http://www.linuxinsider.com/article_images/story_graphics_xlarge/xl-2016-linux-1.jpg) + +> “它能做什么 Windows 不能做的吗?” + +这是许多人在考虑使用 Linux 桌面时的第一个问题。虽然支撑 Linux 的开源哲学对于某些人来说就是一个很好的理由,但是有些人想知道它在外观、感受和功能上有多么不同。在某种程度上,这取决于你是否选择桌面环境或窗口管理器。 + +如果你想要的是闪电般快速的桌面体验且向高效妥协, 那么上述的经典桌面中的窗口管理器可能适合你。 + +### 事实之真相 + +“桌面环境Desktop Environment(DE)”是一个技术术语,指典型的、全功能桌面,即你的操作系统的完整图形化布局。除了显示你的程序,桌面环境还包括应用程序启动器,菜单面板和小部件等组成部分。 + +在 Microsoft Windows 中,桌面环境包括开始菜单、显示打开的程序的任务栏和通知中心,还有与操作系统捆绑在一起的所有 Windows 程序,以及围绕这打开的程序的框架(包括右上角的最小按钮、最大按钮和关闭按钮)。 + +Linux 中有很多相似之处。 + +例如,Linux [Gnome][3] 桌面环境的设计略有不同,但它共享了所有的 Microsoft Windows 的基本元素 - 从应用程序菜单到显示打开的应用程序的面板、通知栏、窗框式程序。 + +窗口程序框架依赖于一个组件来绘制它们,并允许你移动并调整大小:它被称为“窗口管理器Window Manager(WM)”。因为它们都有窗口,所以每个桌面环境都包含一个窗口管理器。 + +然而,并不是每个窗口管理器都是桌面环境的一部分。你可以只运行窗口管理器,并且完全有这么做的需要。 + +### 离开你的环境 + +对本专栏而言,所谓的“窗口管理器”指的是可以那种独立进行的。如果在现有的 Linux 系统上安装了一个窗口管理器,你可以在不关闭系统的情况下注销,在登录屏幕上选择新的窗口管理器,然后重新登录。 + +不过, 在研究你的窗口管理器之前,你可能不想这么做,因为你将会看到一个空白屏幕和稀疏的状态栏,而且它或许能、或许不能点击。 + +通常情况下,可以直接在窗口管理器中直接启动终端,因为这是你编辑其配置文件的方式。在那里你会发现用来启动程序的按键和鼠标组合,你实际上也可以使用你的新设置。 + +例如,在流行的 i3 窗口管理器中,你可以通过按下 `Super` 键(即 `Windows` 键)加 `Enter` 键来启动终端,或者按 `Super + D` 启动应用程序启动器app launcher。你可以在其中输入应用程序名称,然后按 `Enter` 键将其打开。所有已有的应用程序都可以通过这种方式找到,一旦选择后,它们将会全屏打开。 + + [![i3 window manager](http://www.linuxinsider.com/article_images/2017/84473_620x388-small.jpg)][4] + +i3 还是一个平铺式窗口管理器,这意味着它可以确保所有的窗口均匀地扩展到屏幕,既不重叠也不浪费空间。当弹出新窗口时,它会减少现有的窗口,将它们推到一边腾出空间。用户可以以垂直或水平相邻的方式打开下一个窗口。 + +### 功能亦敌亦友 + +当然,桌面环境有其优点。首先,它们提供功能丰富、可识别的界面。每个都有其特征鲜明的风格,但总体而言,它们提供了普适的默认设置,这使得桌面环境从一开始就可以使用。 + +另一个优点是桌面环境带有一组程序和媒体编解码器,允许用户立即完成简单的任务。此外,它们还包括一些方便的功能,如电池监视器、无线小部件和系统通知。 + +与桌面环境的完善相应的,是这种大型软件库和用户体验理念独一无二,这就意味着它们所能做的都是有限度的。这也意味着它们并不总是非常可配置。桌面环境强调的是漂亮的外表,很多时候是金玉其外的。 + +许多桌面环境对系统资源的渴求是众所周知的,所以它们不太喜欢低端硬件。因为在其上运行的视觉效果,还有更多的东西可能会出错。我曾经尝试调整与我正在运行的桌面环境无关的网络设置,然后整个崩溃了。而当我打开一个窗口管理器,我就可以改变设置。 + +那些优先考虑安全性的人可能希望不要桌面环境,因为更多的程序意味着更大的攻击面 —— 也就是坏人可以突破的入口点。 + +然而,如果你想尝试一下桌面环境,XFCE 是一个很好的起点,因为它的较小的软件库消除了一些臃肿,如果你不往里面塞东西,垃圾就会更少。 + +乍一看,它不是最漂亮的,但在下载了一些 GTK 主题包(每个桌面环境都可以提供这些主题或 Qt 主题,而 XFCE 在 GTK 阵营之中),并且在“外观”部分的设置中,你可以轻松地修改。你甚至可以在这个[集中式画廊][5]中找到你最喜欢的主题。 + +### 时间就是生命 + +如果你想了解桌面环境之外可以做什么,你会发现窗口管理器给了你足够的回旋余地。 + +无论如何,窗口管理器都是与定制有关的。事实上,它们的可定制性已经催生了无数的画廊,承载着一个充满活力的社区用户,他们手中的调色板就是窗口管理器。 + +窗口管理器的少量资源需求使它们成为较低规格硬件的理想选择,并且由于大多数窗口管理器不附带任何程序,因此允许喜欢模块化的用户只添加所需的程序。 + +可能与桌面环境最为显著的区别是,窗口管理器通常通过鼠标移动和键盘热键来打开程序或启动器来聚焦效率。 + +键盘驱动的窗口管理器特别流畅,你可以启动新的窗口、输入文本或更多的键盘命令、移动它们,并再次关闭它们,这一切无需将手从键盘中间home row移开。一旦你适应了其设计逻辑,你会惊讶于你能够如此快速地完成任务。 + +尽管它们提供了自由,窗口管理器也有其缺点。最显著的是,它们是赤裸裸的开箱即用。在你可以使用其中一个之前,你必须花时间阅读窗口管理器的文档以获取配置语法,可能还需要更多的时间来找到该语法的窍门。 + +如果你从桌面环境(这是最可能的情况)切换过来,尽管你会有一些用户程序,你也会缺少一些熟悉的东西,如电池指示器和网络小部件,并且需要一些时间来设置新的。 + +如果你想深入窗口管理器,i3 有[完整的文档][6]和简明直白的配置语法。配置文件不使用任何编程语言 - 它只是每行定义一个变量值对。创建热键只要输入 `bindsym`、键盘绑定以及该组合启动的动作即可。 + +虽然窗口管理器不适合每个人,但它们提供了独特的计算体验,而 Linux 是少数允许使用它们的操作系统之一。无论你最终采用哪种模式,我希望这个概观能够给你足够的信息,以便对你所做的选择感到自信 —— 或者有足够的信心跨出您熟悉的区域来看看还有什么可用的。 + +-------------------------------------------------------------------------------- + +作者简介: + +Jonathan Terrasi - 自 2017 年以来一直是 ECT 新闻网专栏作家。他的主要兴趣是计算机安全(特别是 Linux 桌面)、加密和分析政治和时事。他是全职自由作家和音乐家。他的背景包括在芝加哥委员会发表的关于维护人权法案的文章中提供技术评论和分析。 + +----------- + +via: http://www.linuxinsider.com/story/84473.html + +作者:[Jonathan Terrasi][a] +译者:[geekpi](https://github.com/geekpi) +校对:[wxy](https://github.com/wxy) + +本文由 [LCTT](https://github.com/LCTT/TranslateProject) 原创编译,[Linux中国](https://linux.cn/) 荣誉推出 + +[a]: +[1]:http://www.linuxinsider.com/story/84473.html?rss=1# +[2]:http://www.linuxinsider.com/perl/mailit/?id=84473 +[3]:http://en.wikipedia.org/wiki/GNOME +[4]:http://www.linuxinsider.com/article_images/2017/84473_1200x750.jpg +[5]:http://www.xfce-look.org/ +[6]:https://i3wm.org/docs/ diff --git a/published/20170516 What's the point of DevOps.md b/published/201710/20170516 What's the point of DevOps.md similarity index 100% rename from published/20170516 What's the point of DevOps.md rename to published/201710/20170516 What's the point of DevOps.md diff --git a/published/20170529 LFCS sed Command.md b/published/201710/20170529 LFCS sed Command.md similarity index 100% rename from published/20170529 LFCS sed Command.md rename to published/201710/20170529 LFCS sed Command.md diff --git a/translated/talk/20170602 Why working openly is hard when you just want to get stuff done.md b/published/201710/20170602 Why working openly is hard when you just want to get stuff done.md similarity index 69% rename from translated/talk/20170602 Why working openly is hard when you just want to get stuff done.md rename to published/201710/20170602 Why working openly is hard when you just want to get stuff done.md index f6cb33fe9e..25cd7c93c4 100644 --- a/translated/talk/20170602 Why working openly is hard when you just want to get stuff done.md +++ b/published/201710/20170602 Why working openly is hard when you just want to get stuff done.md @@ -1,21 +1,13 @@ 当你只想将事情搞定时,为什么开放式工作这么难? ============================================================ -### 学习使用开放式决策框架来写一本书 +> 学习使用开放式决策框架来写一本书 -![Why working openly is hard when you just want to get stuff done](https://opensource.com/sites/default/files/styles/image-full-size/public/images/business/BIZ_ControlNotDesirable.png?itok=H1PyasHD "Why working openly is hard when you just want to get stuff done") ->图片来源 : opensource.com +![Why working openly is hard when you just want to get stuff done](https://opensource.com/sites/default/files/styles/image-full-size/public/lead-images/BIZ_ControlNotDesirable.png?itok=nrXwSkv7 "Why working openly is hard when you just want to get stuff done") -GSD(get stuff done 的缩写,即搞定)指导着我的工作方式。数年来,我将各种方法论融入我日常工作的习惯中,包括精益方法的反馈循环,和敏捷开发的迭代优化,以此来更好地 GSD(如果把 GSD 当作动词的话)。这意味着我必须非常有效地利用我的时间:列出清晰,各自独立的目标;标记已完成的项目;用迭代的方式地持续推进项目进度。但是当我们默认使用开放的时仍然能够 GSD 吗?又或者 GSD 的方法完全行不通呢?大多数人都认为这会导致糟糕的状况,但我发现事实并不一定这样。 +GSD(get stuff done 的缩写,即搞定)指导着我的工作方式。数年来,我将各种方法论融入我日常工作的习惯中,包括精益方法的反馈循环,和敏捷开发的迭代优化,以此来更好地 GSD(如果把 GSD 当作动词的话)。这意味着我必须非常有效地利用我的时间:列出清晰、各自独立的目标;标记已完成的项目;用迭代的方式地持续推进项目进度。但是当我们以开放为基础时仍然能够 GSD 吗?又或者 GSD 的方法完全行不通呢?大多数人都认为这会导致糟糕的状况,但我发现事实并不一定这样。 -在开放的环境中工作,遵循[开放式决策框架][6]中的指导,会让项目起步变慢。但是在最近的一个项目中,我们作出了一个决定,一个从开始就正确的决定:以开放的方式工作,并与我们的社群一起合作。 - -关于开放式组织的资料 - -* [下载《开放式组织 IT 文化变革指南》][1] -* [下载《开放式组织领袖手册》][2] -* [什么是开放式组织][3] -* [什么是开放决策][4] +在开放的环境中工作,遵循[开放式决策框架][6]Open Decision Framework中的指导,会让项目起步变慢。但是在最近的一个项目中,我们作出了一个决定,一个从开始就正确的决定:以开放的方式工作,并与我们的社群一起合作。 这是我们能做的最好的决定。 @@ -23,13 +15,13 @@ GSD(get stuff done 的缩写,即搞定)指导着我的工作方式。数 ### 建立社区 -2014 年 10 月,我接手了一个新的项目:当时红帽的 CEO Jim Whitehurst 即将推出一本新书《开放式组织》,我要根据书中提出的概念,建立一个社区。“太棒了,这听起来是一个挑战,我加入了!”我这样想。但不久,[冒牌者综合征][7]便出现了,我又开始想:“我们究竟要做什么呢?怎样才算成功呢?” +2014 年 10 月,我接手了一个新的项目:当时红帽的 CEO Jim Whitehurst 即将推出一本新书《开放式组织》The Open Organization,我要根据书中提出的概念,建立一个社区。“太棒了,这听起来是一个挑战,我加入了!”我这样想。但不久,[冒牌者综合征][7]便出现了,我又开始想:“我们究竟要做什么呢?怎样才算成功呢?” 让我剧透一下,在这本书的结尾处,Jim 鼓励读者访问 Opensource.com,继续探讨 21 世纪的开放和管理。所以,在 2015 年 5 月,我们的团队在网站上建立了一个新的板块来讨论这些想法。我们计划讲一些故事,就像我们在 Opensource.com 上常做的那样,只不过这次围绕着书中的观点与概念。之后,我们每周都发布新的文章,在 Twitter 上举办了一个在线的读书俱乐部,还将《开放式组织》打造成了系列书籍。 我们内部独自完成了该系列书籍的前三期,每隔六个月发布一期。每完成一期,我们就向社区发布。然后我们继续完成下一期的工作,如此循环下去。 -这种工作方式,让我们看到了很大的成功。近 3000 人订阅了[该系列的新书][9],《开放式组织领袖手册》。我们用 6 个月的周期来完成这个项目,这样新书的发行日正好是前书的两周年纪念日。 +这种工作方式,让我们看到了很大的成功。近 3000 人订阅了[该系列的新书][9]:《开放式组织领袖手册》。我们用 6 个月的周期来完成这个项目,这样新书的发行日正好是前书的两周年纪念日。 在这样的背景下,我们完成这本书的方式是简单直接的:针对开放工作这个主题,我们收集了最好的故事,并将它们组织起来形成文章,招募作者填补一些内容上的空白,使用开源工具调整字体样式,与设计师一起完成封面,最终发布这本书。这样的工作方式使得我们能按照自己的时间线(GSD)全速前进。到[第三本书][10]时,我们的工作流已经基本完善了。 @@ -39,59 +31,55 @@ GSD(get stuff done 的缩写,即搞定)指导着我的工作方式。数 开放式决策框架列出了组成开放决策制定过程的 4 个阶段。下面是我们在每个阶段中的工作情况(以及开放是如何帮助完成工作的)。 -### 1\. 构思 +#### 1、 构思 我们首先写了一份草稿,罗列了对项目设想的愿景。我们需要拿出东西来和潜在的“顾客”分享(在这个例子中,“顾客”指潜在的利益相关者和作者)。然后我们约了一些领域专家面谈,这些专家能够给我们直接的诚实的意见。这些专家表现出的热情与他们提供的指导验证了我们的想法,同时提出了反馈意见使我们能继续向前。如果我们没有得到这些验证,我们会退回到我们最初的想法,再决定从哪里重新开始。 -### 2\. 计划与研究 +#### 2、 计划与研究 -经过几次面谈,我们准备在 [Opensource.com 上公布这个项目][11]。同时,我们在 [Github 上也公布了这个项目][12], 提供了项目描述,预计的时间线,并阐明了我们所受的约束。这次公布得到了很好的效果,我们最初计划的目录中欠缺了一些内容,在项目公布之后的 72 小时内就被补充完整了。另外(也是更重要的),读者针对一些章节,提出了本不在我们计划中的想法,但是读者觉得这些想法能够补充我们最初设想的版本。 +经过几次面谈,我们准备在 [Opensource.com 上公布这个项目][11]。同时,我们在 [Github 上也启动了这个项目][12],提供了项目描述、预计的时间线,并阐明了我们所受的约束。这次公布得到了很好的效果,我们最初计划的目录中欠缺了一些内容,在项目公布之后的 72 小时内就被补充完整了。另外(也是更重要的),读者针对一些章节,提出了本不在我们计划中的想法,但是读者觉得这些想法能够补充我们最初设想的版本。 -我们体会到了 [Linus 法则][16]: "With more eyes, all _typos_ are shallow." +回顾过去,我觉得在项目的第一和第二个阶段,开放项目并不会影响我们搞定项目的能力。事实上,这样工作有一个很大的好处:发现并填补内容的空缺。我们不只是填补了空缺,我们是迅速地填补了空缺,并且还是用我们自己从未考虑过的点子。这并不一定要求我们做更多的工作,只是改变了我们的工作方式。我们动用有限的人脉,邀请别人来写作,再组织收到的内容,设置上下文,将人们导向正确的方向。 -回顾过去,我觉得在项目的第一和第二个阶段,开放项目并不会影响我们搞定项目的能力。事实上,这样工作有一个很大的好处:发现并填补内容的空缺。我们不只是填补了空缺,我们是迅速地就填补了空缺,并且还是用我们自己从未考虑过的点子。这并不一定要求我们做更多的工作,只是改变了我们的工作方式。我们动用有限的人脉,邀请别人来写作,再组织收到的内容,设置上下文,将人们导向正确的方向。 - -### 3\. 设计,开发和测试 +#### 3、 设计,开发和测试 项目的这个阶段完全围绕项目管理,管理一些像猫一样特立独行的人,并处理项目的预期。我们有明确的截止时间,我们提前沟通,频繁沟通。我们还使用了一个战略:列出了贡献者和利益相关者,在项目的整个过程中向他们告知项目的进度,尤其是我们在 Github 上标出的里程碑。 -最后,我们的书需要一个名字。我们收集了许多反馈,指出书名应该是什么,更重要的反馈指出了书名不应该是什么。我们通过 [Github 上的 issue][13] 收集反馈意见,并公开表示我们的团队将作最后的决定。当我们准备宣布最后的书名时,我的同事 Bryan Behrenshausen 做了很好的工作,[分享了我们作出决定的过程][14]。人们似乎对此感到高兴——即使他们不同意我们最后的书名。 +最后,我们的书需要一个名字。我们收集了许多反馈,指出书名应该是什么,更重要的是反馈指出了书名不应该是什么。我们通过 [Github 上的工单][13]收集反馈意见,并公开表示我们的团队将作最后的决定。当我们准备宣布最后的书名时,我的同事 Bryan Behrenshausen 做了很好的工作,[分享了我们作出决定的过程][14]。人们似乎对此感到高兴——即使他们不同意我们最后的书名。 -书的“测试”阶段需要大量的[校对][15]。社区成员真的参与到回答这个“求助”贴中来。我们在 GitHub issue 上收到了大约 80 条意见,汇报校对工作的进度(更不用说通过电子邮件和其他反馈渠道获得的许多额外的反馈)。 +书的“测试”阶段需要大量的[校对][15]。社区成员真的参与到回答这个“求助”贴中来。我们在 GitHub 工单上收到了大约 80 条意见,汇报校对工作的进度(更不用说通过电子邮件和其他反馈渠道获得的许多额外的反馈)。 -关于搞定任务:在这个阶段,我们亲身体会了 [Linus 法则][16]:"With more eyes, all _typos_ are shallow." 如果我们像前三本书一样自己独立完成,那么整个校对的负担就会落在我们的肩上(就像这些书一样)!相反,社区成员慷慨地帮我们承担了校对的重担,我们的工作从自己校对(尽管我们仍然做了很多工作)转向管理所有的 change requests。对我们团队来说,这是一个受大家欢迎的改变;对社区来说,这是一个参与的机会。如果我们自己做的话,我们肯定能更快地完成校对,但是在开放的情况下,我们在截止日期之前发现了更多的错误,这一点毋庸置疑。 +关于搞定任务:在这个阶段,我们亲身体会了 [Linus 法则][16]:“众目之下,_笔误_无所遁形。With more eyes, all _typos_ are shallow.” 如果我们像前三本书一样自己独立完成,那么整个校对的负担就会落在我们的肩上(就像这些书一样)!相反,社区成员慷慨地帮我们承担了校对的重担,我们的工作从自己校对(尽管我们仍然做了很多工作)转向管理所有的 change requests。对我们团队来说,这是一个受大家欢迎的改变;对社区来说,这是一个参与的机会。如果我们自己做的话,我们肯定能更快地完成校对,但是在开放的情况下,我们在截止日期之前发现了更多的错误,这一点毋庸置疑。 -### 4\. Launch - -### 4\. 发布 +#### 4、 发布 好了,我们现在推出了这本书的最终版本。(或者只是第一版?) -遵循开放决策框架是《IT 文化变革指南》成功的关键。 - 我们把发布分为两个阶段。首先,根据我们的公开的项目时间表,在最终日期之前的几天,我们安静地推出了这本书,以便让我们的社区贡献者帮助我们测试[下载表格][17]。第二阶段也就是现在,这本书的[通用版][18]的正式公布。当然,我们在发布后的仍然接受反馈,开源方式也正是如此。 ### 成就解锁 -遵循开放式决策框架是《IT 文化变革指南》成功的关键。通过与客户和利益相关者的合作,分享我们的制约因素,工作透明化,我们甚至超出了自己对图书项目的期望。 +遵循开放式决策框架是《IT 文化变革指南》Guide to IT Culture Change成功的关键。通过与客户和利益相关者的合作,分享我们的制约因素,工作透明化,我们甚至超出了自己对图书项目的期望。 我对整个项目中的合作,反馈和活动感到非常满意。虽然有一段时间内没有像我想要的那样快速完成任务,这让我有一种焦虑感,但我很快就意识到,开放这个过程实际上让我们能完成更多的事情。基于上面我的概述这一点显而易见。 -所以也许我应该重新考虑我的 GSD 心态,并将其扩展到 GMD:Get **more** done,搞定**更多**工作,并且就这个例子说,取得更好的结果。 +所以也许我应该重新考虑我的 GSD 心态,并将其扩展到 GMD:Get **More** Done,搞定**更多**工作,并且就这个例子说,取得更好的结果。 + +(题图:opensource.com) -------------------------------------------------------------------------------- 作者简介: -Jason Hibbets - Jason Hibbets 是 Red Hat 企业营销中的高级社区传播者,也是 Opensource.com 的社区经理。 他自2003年以来一直在 Red Hat,并且是开源城市基金会的创立者。之前的职位包括高级营销专员,项目经理,Red Hat 知识库维护人员和支持工程师。 +Jason Hibbets - Jason Hibbets 是 Red Hat 企业营销中的高级社区传播者,也是 Opensource.com 的社区经理。 他自2003 年以来一直在 Red Hat,并且是开源城市基金会的创立者。之前的职位包括高级营销专员、项目经理、Red Hat 知识库维护人员和支持工程师。 ----------- via: https://opensource.com/open-organization/17/6/working-open-and-gsd -作者:[Jason Hibbets ][a] +作者:[Jason Hibbets][a] 译者:[explosic4](https://github.com/explosic4) -校对:[校对者ID](https://github.com/校对者ID) +校对:[wxy](https://github.com/wxy) 本文由 [LCTT](https://github.com/LCTT/TranslateProject) 原创编译,[Linux中国](https://linux.cn/) 荣誉推出 diff --git a/published/201710/20170617 What all you need to know about HTML5.md b/published/201710/20170617 What all you need to know about HTML5.md new file mode 100644 index 0000000000..cd3851589e --- /dev/null +++ b/published/201710/20170617 What all you need to know about HTML5.md @@ -0,0 +1,311 @@ +关于 HTML5 你需要了解的基础知识 +============================================================ + +![](https://i0.wp.com/opensourceforu.com/wp-content/uploads/2017/05/handwritten-html5-peter-booth-e-plus-getty-images-56a6faec5f9b58b7d0e5d1cf.jpg?resize=700%2C467) + +> HTML5 是第五个且是当前的 HTML 版本,它是用于在万维网上构建和呈现内容的标记语言。本文将帮助读者了解它。 + +HTML5 通过 W3C 和Web 超文本应用技术工作组Web Hypertext Application Technology Working Group之间的合作发展起来。它是一个更高版本的 HTML,它的许多新元素可以使你的页面更加语义化和动态。它是为所有人提供更好的 Web 体验而开发的。HTML5 提供了很多的功能,使 Web 更加动态和交互。 + +HTML5 的新功能是: + +* 新标签,如 `
` 和 `
` +* 用于 2D 绘图的 `` 元素 +* 本地存储 +* 新的表单控件,如日历、日期和时间 +* 新媒体功能 +* 地理位置 + +HTML5 还不是正式标准(LCTT 译注:HTML5 已于 2014 年成为“推荐标准”),因此,并不是所有的浏览器都支持它或其中一些功能。开发 HTML5 背后最重要的原因之一是防止用户下载并安装像 Silverlight 和 Flash 这样的多个插件。 + +**新标签和元素** + +- **语义化元素:** 图 1 展示了一些有用的语义化元素。 +- **表单元素:** HTML5 中的表单元素如图 2 所示。 +- **图形元素:** HTML5 中的图形元素如图 3 所示。 +- **媒体元素:** HTML5 中的新媒体元素如图 4 所示。 + + +[![](https://i0.wp.com/opensourceforu.com/wp-content/uploads/2017/05/Figure-1-7.jpg?resize=350%2C277)][3] + +*图 1:语义化元素* + +[![](https://i1.wp.com/opensourceforu.com/wp-content/uploads/2017/05/Figure-2-5.jpg?resize=350%2C108)][4] + +*图 2:表单元素* + +[![](https://i0.wp.com/opensourceforu.com/wp-content/uploads/2017/05/Figure-3-2.jpg?resize=350%2C72)][5] + +*图 3:图形元素* + +[![](https://i0.wp.com/opensourceforu.com/wp-content/uploads/2017/05/Figure-4-2.jpg?resize=350%2C144)][6] + +*图 4:媒体元素* + +### HTML5 的高级功能 + +#### 地理位置 + +这是一个 HTML5 API,用于获取网站用户的地理位置,用户必须首先允许网站获取他或她的位置。这通常通过按钮和/或浏览器弹出窗口来实现。所有最新版本的 Chrome、Firefox、IE、Safari 和 Opera 都可以使用 HTML5 的地理位置功能。 + +地理位置的一些用途是: + +* 公共交通网站 +* 出租车及其他运输网站 +* 电子商务网站计算运费 +* 旅行社网站 +* 房地产网站 +* 在附近播放的电影的电影院网站 +* 在线游戏 +* 网站首页提供本地标题和天气 +* 工作职位可以自动计算通勤时间 + +**工作原理:** 地理位置通过扫描位置信息的常见源进行工作,其中包括以下: + +* 全球定位系统(GPS)是最准确的 +* 网络信号 - IP地址、RFID、Wi-Fi 和蓝牙 MAC地址 +* GSM/CDMA 蜂窝 ID +* 用户输入 + +该 API 提供了非常方便的函数来检测浏览器中的地理位置支持: + +``` +if (navigator.geolocation) { +// do stuff +} +``` +`getCurrentPosition` API 是使用地理位置的主要方法。它检索用户设备的当前地理位置。该位置被描述为一组地理坐标以及航向和速度。位置信息作为位置对象返回。 + +语法是: + +``` +getCurrentPosition(showLocation, ErrorHandler, options); +``` + +* `showLocation`:定义了检索位置信息的回调方法。 +* `ErrorHandler`(可选):定义了在处理异步调用时发生错误时调用的回调方法。 +* `options` (可选): 定义了一组用于检索位置信息的选项。 + +我们可以通过两种方式向用户提供位置信息:测地和民用。 + +1. 描述位置的测地方式直接指向纬度和经度。 +2. 位置信息的民用表示法是人类可读的且容易理解。 + +如下表 1 所示,每个属性/参数都具有测地和民用表示。 + + [![](https://i0.wp.com/opensourceforu.com/wp-content/uploads/2017/05/table-1.jpg?resize=350%2C132)][7] + +图 5 包含了一个位置对象返回的属性集。 + +[![](https://i0.wp.com/opensourceforu.com/wp-content/uploads/2017/05/Figure5-1.jpg?resize=350%2C202)][8] + +*图5:位置对象属性* + +#### 网络存储 + +在 HTML 中,为了在本机存储用户数据,我们需要使用 JavaScript cookie。为了避免这种情况,HTML5 已经引入了 Web 存储,网站利用它在本机上存储用户数据。 + +与 Cookie 相比,Web 存储的优点是: + +* 更安全 +* 更快 +* 存储更多的数据 +* 存储的数据不会随每个服务器请求一起发送。只有在被要求时才包括在内。这是 HTML5 Web 存储超过 Cookie 的一大优势。 + +有两种类型的 Web 存储对象: + +1. 本地 - 存储没有到期日期的数据。 +2. 会话 - 仅存储一个会话的数据。 + +**如何工作:** `localStorage` 和 `sessionStorage` 对象创建一个 `key=value` 对。比如: `key="Name"`,`   value="Palak"`。 + +这些存储为字符串,但如果需要,可以使用 JavaScript 函数(如 `parseInt()` 和 `parseFloat()`)进行转换。 + +下面给出了使用 Web 存储对象的语法: + +- 存储一个值: + - `localStorage.setItem("key1", "value1");` + - `localStorage["key1"] = "value1";` +- 得到一个值: + - `alert(localStorage.getItem("key1"));` + - `alert(localStorage["key1"]);` +- 删除一个值: + -`removeItem("key1");` +- 删除所有值: + - `localStorage.clear();` + +#### 应用缓存(AppCache) + +使用 HTML5 AppCache,我们可以使 Web 应用程序在没有 Internet 连接的情况下脱机工作。除 IE 之外,所有浏览器都可以使用 AppCache(截止至此时)。 + +应用缓存的优点是: + +* 网页浏览可以脱机 +* 页面加载速度更快 +* 服务器负载更小 + +`cache manifest` 是一个简单的文本文件,其中列出了浏览器应缓存的资源以进行脱机访问。 `manifest` 属性可以包含在文档的 HTML 标签中,如下所示: + +``` + +... + +``` + +它应该在你要缓存的所有页面上。 + +缓存的应用程序页面将一直保留,除非: + +1. 用户清除它们 +2. `manifest` 被修改 +3. 缓存更新 + +#### 视频 + +在 HTML5 发布之前,没有统一的标准来显示网页上的视频。大多数视频都是通过 Flash 等不同的插件显示的。但 HTML5 规定了使用 video 元素在网页上显示视频的标准方式。 + +目前,video 元素支持三种视频格式,如表 2 所示。 + + [![](https://i0.wp.com/opensourceforu.com/wp-content/uploads/2017/05/table-2.jpg?resize=350%2C115)][9] + +下面的例子展示了 video 元素的使用: + +``` + + + + + + + + +``` + +例子使用了 Ogg 文件,并且可以在 Firefox、Opera 和 Chrome 中使用。要使视频在 Safari 和未来版本的 Chrome 中工作,我们必须添加一个 MPEG4 和 WebM 文件。 + +`video` 元素允许多个 `source` 元素。`source` 元素可以链接到不同的视频文件。浏览器将使用第一个识别的格式,如下所示: + +``` + +``` + +[![](https://i0.wp.com/opensourceforu.com/wp-content/uploads/2017/05/Figure6-1.jpg?resize=350%2C253)][10] + +*图6:Canvas 的输出* + +#### 音频 + +对于音频,情况类似于视频。在 HTML5 发布之前,在网页上播放音频没有统一的标准。大多数音频也通过 Flash 等不同的插件播放。但 HTML5 规定了通过使用音频元素在网页上播放音频的标准方式。音频元素用于播放声音文件和音频流。 + +目前,HTML5 `audio` 元素支持三种音频格式,如表 3 所示。 + + [![](https://i1.wp.com/opensourceforu.com/wp-content/uploads/2017/05/table-3.jpg?resize=350%2C123)][11] + +`audio` 元素的使用如下所示: + +``` + + + + +