Skip to content

Commit

Permalink
进行一些小的修补
Browse files Browse the repository at this point in the history
  • Loading branch information
tkchu committed Dec 5, 2015
1 parent 543da83 commit 5d00199
Show file tree
Hide file tree
Showing 10 changed files with 123 additions and 180 deletions.
29 changes: 1 addition & 28 deletions book/architecture-performance-and-games.markdown
Original file line number Diff line number Diff line change
Expand Up @@ -167,11 +167,6 @@ extensibility should be engineered in so future changes are easier to make.
每当你添加了一层抽象或者支持扩展的部分,你是**你以后需要灵活性。
添加代码和复杂性到游戏中,这都需要时间来开发,调试和维护。

That effort pays off if you guess right and end up touching that code later. But
<span name="yagni">predicting</span> the future is *hard*, and when that
modularity doesn't end up being helpful, it quickly becomes actively harmful.
After all, it is more code you have to deal with.

如果你猜对了,后来接触了代码,那么功夫不负有心人。
但<span name="yagni">预测</span>未来*很难*,如果模块化最终没有帮助,那它就有伤害。
毕竟,你得处理更多的代码。
Expand All @@ -190,12 +185,6 @@ After all, it is more code you have to deal with.
理论上,解耦意味着在扩展代码之前需要了解的代码更少,
但抽象层本身就会填满你的心灵暂存磁盘。

Codebases like this are what turn people *against* software architecture, and
design patterns in particular. It's easy to get so wrapped up in the code itself
that you lose sight of the fact that you're trying to ship a *game*. The siren
song of extensibility sucks in countless developers who spend years working on
an "engine" without ever figuring out what it's an engine *for*.

像这样的代码库让人*反对*软件架构,特别是设计模式。
人们很容易沉浸在代码中而忽略你要发布*游戏*的这点。
无数的开发者听着加强可扩展性的警报,花费多年时间制作“引擎”,
Expand Down Expand Up @@ -261,13 +250,7 @@ an "engine" without ever figuring out what it's an engine *for*.
良好的设计意味着你在屏幕上看到和获取反馈之前要消耗很长时间。
如果最后证明这个点子不对,那么当你删除代码的时候,那些花在让代码更优雅的时间就完全浪费了。

Prototyping -- slapping together code that's just barely functional enough to
answer a design question -- is a perfectly legitimate programming practice.
There is a very large caveat, though. If you write throwaway code, you *must*
ensure you're able to throw it away. I've seen bad managers play this game time
and time again:

原型——一坨勉强拼凑在一起,只能回答设计问题简单代码——是一个完全合理的编程习惯。
原型——一坨勉强拼凑在一起,只能回答设计问题的简单代码——是一个完全合理的编程习惯。
虽然当你写一次性代码的时候,*必须*保证你可以扔掉它。
我见过很多次糟糕的经理人在玩这种把戏:

Expand Down Expand Up @@ -319,12 +302,6 @@ and time again:
从我收到的邮件看,这伤了很多人的心,特别是那些只是想做个游戏的人。
它似乎是在恐吓,“没有正确的答案,只有不同的口味的错误。”

But, to me, this is exciting! Look at any field that people dedicate careers to
mastering, and in the center you will always find a set of intertwined
constraints. After all, if there was an easy answer, everyone would just do
that. A field you can master in a week is ultimately boring. You don't hear of
someone's distinguished career in <span name="ditch">ditch digging</span>.

但,对我来说,这让人兴奋!看看任何人们从事的领域,
你总能发现某些相互抵触的限制。无论如何,如果有简单的答案,每个人都会那么做。
一周就能掌握的领域是很无聊的。你从来没有听说过有人讨论<span name="ditch">挖坑事业</span>。
Expand All @@ -347,10 +324,6 @@ someone's distinguished career in <span name="ditch">ditch digging</span>.
在我现在的代码中,我努力去写最简单,最直接的解决方案。
你读过这种代码后,完全理解了它在做什么,想不出其他完成的方法。

I aim to get the data structures and algorithms right (in about that order) and
then go from there. I find if I can keep things simple, there's less code
overall. That means less code to load into my head in order to change it.

我的目的是正确获得数据结构和算法(大致是这样的先后),然后在从那里开始。
我发现如果能让事物变得简单,就有更少的代码,
就意味着改动时有更少的代码载入脑海。
Expand Down
54 changes: 25 additions & 29 deletions book/bytecode.markdown
Original file line number Diff line number Diff line change
Expand Up @@ -554,11 +554,7 @@ Techniques, and Tools*](http://en.wikipedia.org/wiki/Compilers:_Principles,_Tech
尤其是使用它的人没有很高的技术。
一个没有花几年时间习惯编译器怒吼的人很难写出没有语法错误文本。

Instead, you can build an app that lets users "script" by clicking and dragging
little boxes, pulling down menu items, or whatever else makes sense for the
kind of behavior you want them to create.

你可以建立一个应用程序,用户通过单击拖动小盒子,下拉菜单项,或任何有意义的行为创建“脚本”。
你可以建立一个应用程序,用户通过单击拖动小盒子,下拉菜单项,或任何有意义的行为创建“脚本”,从而创建行为。

<span name="text"></span>

Expand Down Expand Up @@ -646,19 +642,19 @@ Lua转换为基于寄存器的虚拟机从而变得更快,这为其博得了
指令集定义了你在字节码中可以干什么,不能干什么的边界,它对虚拟机性能也有很大的影响。
这里有一个清单,记录了不同种类的,你可能需要的指令:

 * **外部原语。**这是虚拟机与引擎其他部分交互并影响玩家看到的部分。它们控制了字节码可以表达的真实行为。如果没有这些,你的虚拟机除了消耗CPU循环以外一无所得。
* **外部原语。**这是虚拟机与引擎其他部分交互并影响玩家看到的部分。它们控制了字节码可以表达的真实行为。如果没有这些,你的虚拟机除了消耗CPU循环以外一无所得。

* **内部原语**这些语句在虚拟机内操作数值——比如文字,算术,比较操作,以及操纵栈的指令。
* **内部原语**这些语句在虚拟机内操作数值——比如文字,算术,比较操作,以及操纵栈的指令。

 * **控制流。**我们的例子没有包含这些,但当你需要有条件执行或循环执行,你需要控制流。在字节码这样底层的语言,它们出奇的简单:跳转。
* **控制流。**我们的例子没有包含这些,但当你需要有条件执行或循环执行,你需要控制流。在字节码这样底层的语言,它们出奇的简单:跳转。

在我们的指令循环中,我们有一个索引来跟踪我们到了字节码的哪里。
跳转指令做的是修改这个索引并改变将要执行的。
换言之,这是一个`goto`。你可以基于它制定各种更高级别的控制流。

* **抽象。**如果你的用户开始在数据中定义*很多*的东西,最终他们要重用字节码的部分位,而不是复制和粘贴。你可能需要调用过程这样的东西。
* **抽象。**如果你的用户开始在数据中定义*很多*的东西,最终他们要重用字节码的部分位,而不是复制和粘贴。你可能需要调用过程这样的东西。

   最简单的形式中,过程并不比跳转复杂。
最简单的形式中,过程并不比跳转复杂。
唯一不同的是,在VM运行后者时,栈会存储第二次*返回*的位置。
当执行“call”指令时,将当前指令索引压入栈中,然后跳转到被调用的字节码。
当它到了“return”,虚拟机从堆栈弹出索引,然后调回索引指示的位置。
Expand All @@ -670,27 +666,27 @@ Lua转换为基于寄存器的虚拟机从而变得更快,这为其博得了
一个更加完整的虚拟机支持不同的数据类型:字符串,对象,列表等。
你必须决定如何在内部存储这些值。

* **单一数据类型:**
* **单一数据类型:**

* *简单易用*你不必担心标记,转换,或类型检查。
* *简单易用*你不必担心标记,转换,或类型检查。

* *无法使用不同的数据类型。*这是明显的缺点。将不同类型成塞进单一的表示方式——将数字存储为字符串——这是找打。
* *无法使用不同的数据类型。*这是明显的缺点。将不同类型成塞进单一的表示方式——将数字存储为字符串——这是找打。

* **有标记的类型:**
* **有标记的类型:**

这是动态类型语言中常见的表示法。所有的值有两部分。第一部分是类型标记——一个`enum`——标识存储了什么数据类型。这些位的其余部分会被解释为这种类型:

^code tagged-value

  * *数值知道其类型。*这个表示法的好处是可在运行时检查值的类型。这对动态分配是很重要的,可以确保没有在类型上面执行其不支持的操作。
* *数值知道其类型。*这个表示法的好处是可在运行时检查值的类型。这对动态分配是很重要的,可以确保没有在类型上面执行其不支持的操作。

   * *它消耗更多内存。*每个值都要带一些额外的位来识别类型。在像VM这样的底层,这里几位和那里几位,总量就会快速增加。
* *它消耗更多内存。*每个值都要带一些额外的位来识别类型。在像VM这样的底层,这里几位和那里几位,总量就会快速增加。

 * **未标记的union:**
* **未标记的union:**

这像前面一样使用union,但是它*没有*类型标识。你可以将这些位表示为不同的类型,由你确保没有搞错值的类型。

    这是<span name="untyped">静态类型</span>语言在内存中表示事物的方式。
这是<span name="untyped">静态类型</span>语言在内存中表示事物的方式。
由于类型系统在编译时保证没弄错值的类型,你不需要在运行时对其进行验证。

<aside name="untyped">
Expand All @@ -699,11 +695,11 @@ Lua转换为基于寄存器的虚拟机从而变得更快,这为其博得了

</aside>

     * *结构紧凑。*你找不到比只存储你需要的值更加有效率的存储方式。
* *结构紧凑。*你找不到比只存储你需要的值更加有效率的存储方式。

     * *速度快。*没有类型标识意味着你在运行时无需消耗周期检查它们的类型。这是静态类型语言往往比动态类型语言快的原因之一。
* *速度快。*没有类型标识意味着你在运行时无需消耗周期检查它们的类型。这是静态类型语言往往比动态类型语言快的原因之一。

     * *不安全。*<span name="unsafe">这</span>是真正的代价。一块坏字节码,会让你误解一个值,让你把数字误解为指针,会破坏游戏安全或使其崩溃。
* *不安全。* <span name="unsafe">这</span>是真正的代价。一块坏字节码,会让你误解一个值,让你把数字误解为指针,会破坏游戏安全或使其崩溃。

<aside name="unsafe">

Expand All @@ -713,25 +709,25 @@ Lua转换为基于寄存器的虚拟机从而变得更快,这为其博得了

</aside>

 * **接口:**
* **接口:**

    多种类型值的面向对象解决方案是通过多态。接口为不同的类型测试和转换提供虚拟方法,如下:
多种类型值的面向对象解决方案是通过多态。接口为不同的类型测试和转换提供虚拟方法,如下:

^code value-interface

    然后你为每个特定的数据类型设计特定的类,如:
然后你为每个特定的数据类型设计特定的类,如:

^code int-value

     * *开放式。*您可以在虚拟机的核心之外定义新的值类型,只要它们实现了基本接口就行。
* *开放式。*您可以在虚拟机的核心之外定义新的值类型,只要它们实现了基本接口就行。

     * *面向对象。*如果你坚持OOP原则,这是做事情“正确”的方式,为特定类型使用多态分配行为,而不是在标签上做switch之类的。
* *面向对象。*如果你坚持OOP原则,这是做事情“正确”的方式,为特定类型使用多态分配行为,而不是在标签上做switch之类的。

    * *冗长。*您必须定义一个单独的类,包含了每个数据类型的相关行为。注意在前面的例子中,我们定义了*所有*的类型。在这里,我们只包含了一个!
* *冗长。*您必须定义一个单独的类,包含了每个数据类型的相关行为。注意在前面的例子中,我们定义了*所有*的类型。在这里,我们只包含了一个!

    * *低效。*为了多使用态,你必须使用指针,这意味着即使是短小的值,如布尔和数字,也得裹在分配在堆中的对象里。每使用一个值,你就得做一次虚方法调用。
* *低效。*为了多使用态,你必须使用指针,这意味着即使是短小的值,如布尔和数字,也得裹在分配在堆中的对象里。每使用一个值,你就得做一次虚方法调用。

       在虚拟机核心之类的地方,像这样的小性能影响迅速叠加。事实上,这引起了许多我们试图在解释器模式中避免的问题。只是现在的问题不在*代码*中,而是在**中。
在虚拟机核心之类的地方,像这样的小性能影响迅速叠加。事实上,这引起了许多我们试图在解释器模式中避免的问题。只是现在的问题不在*代码*中,而是在**中。

我的建议是,如果你可以只用单一数据类型,那就这么做。除此以外,使用标记的union。这是世界上几乎每个语言解释器做的事情。

Expand Down
3 changes: 0 additions & 3 deletions book/observer.markdown
Original file line number Diff line number Diff line change
Expand Up @@ -60,9 +60,6 @@

^code physics-update

All it does is say, "Uh, I don't know if anyone
cares, but this thing just fell. Do with that as you will."

<span name="subtle">他做的就是</span>,“额,我不知道有谁感兴趣,但是这个东西刚刚掉下去了。做你想做的事吧。”

<aside name="subtle">
Expand Down
6 changes: 0 additions & 6 deletions book/service-locator.markdown
Original file line number Diff line number Diff line change
Expand Up @@ -21,12 +21,6 @@ NPC狙击手开了一枪,射出子弹(AI)。

^code 15

Either gets us where we're trying to go, but we stumbled into some sticky
coupling along the way. Every place in the game calling into our audio system
directly references the concrete `AudioSystem` class and the mechanism for
accessing it -- either as a static class or a <a class="gof-pattern"
href="singleton.html">singleton</a>.

每种都能让我们获得我们想要的,但是我们绊倒在一些微妙的耦合上。
每个调用音频系统的游戏部分直接引用了具体的`AudioSystem`类,和获取它的机制——是静态类还是一个<a class="gof-pattern" href="singleton.html">单例。</a>

Expand Down
6 changes: 2 additions & 4 deletions book/subclass-sandbox.markdown
Original file line number Diff line number Diff line change
Expand Up @@ -71,10 +71,8 @@

<aside name="wide">

Lately, you find a lot of people criticizing inheritance in object-oriented
languages. Inheritance *is* problematic -- there's really no deeper coupling in
a codebase than the one between a base class and its subclass -- but I find
*wide* inheritance trees to be easier to work with than *deep* ones.
最近,你发现很多人批评面向对象语言中的继承。
继承**有问题——在代码库中没有比父类子类之间的耦合更深的了——但我发现*宽阔的*继承树比起*深的*更好处理。

</aside>

Expand Down
Loading

0 comments on commit 5d00199

Please sign in to comment.