首先,让我们看一下上下文:这是一位游戏设计师在一个博客上写的,主题是从Cell BE CPU看性能的最后下降。换句话说:它涉及控制台游戏编程,更具体地说是关于PlayStation 3的控制台游戏编程。
现在,游戏程序员是一群好奇的人,而控制台游戏程序员更是如此,而Cell BE是一个相当奇怪的CPU。(索尼为PlayStation 4采用更传统的设计是有原因的!)
因此,我们必须在这种情况下查看这些语句。
该博客文章中也有一些简化。特别是,这种谎言#2表现不佳。
我认为从某种意义上讲,从现实世界中抽象出来的一切都是模型。由于软件不是真实的而是虚拟的,因此它始终是抽象,因此始终是模型。但!模型不必在现实世界上具有清晰的1:1映射。毕竟,首先是使它成为模型的原因。
因此,从某种意义上说,作者显然是错误的:软件是一个模型。期。从某种意义上说,他是对的:该模型实际上根本不必类似于现实世界。
我将提供一个示例,这些年来,我已经在其他一些答案中给出了(著名的OO 101银行帐户简介示例)。这是几乎几乎所有OO类中的银行帐户的外观:
class Account {
var balance: Decimal
def transfer(amount: Decimal, target: Account) = {
balance -= amount
target.balance += amount
}
}
所以:balance
是数据,transfer
是操作。
但!这是几乎几乎所有银行软件中的银行帐户的外观:
class TransactionSlip {
val transfer(amount: Decimal, from: Account, to: Account)
}
class Account {
def balance =
TransactionLog.filter(t => t.to == this).map(_.amount).sum -
TransactionLog.filter(t => t.from == this).map(_.amount).sum
}
因此,现在transfer
是数据,balance
是一个操作(在事务日志上的左折)。(您还将注意到,它TransactionSlip
是不可变的,balance
是一个纯函数,TransactionLog
可以是仅附加的“几乎”不可变的数据结构……我敢肯定,很多人在第一个实现中发现了明显的并发错误,现在这些错误已神奇地消失了)
请注意,这两个都是模型。这两个都是同等有效的。这两个都是正确的。这两个模型都是一样的。但是,它们彼此之间是完全对偶的:一个模型中的所有数据都是另一模型中的操作,而一个模型中的所有操作则是另一模型中的数据。
因此,问题不在于是否要在代码中建模“真实世界”,而是如何建模。
事实证明,第二种模式实际上也是银行在现实世界中的运作方式。正如我暗示上方,这第二个模型主要是不可改变的,纯净,不受并发错误,这实际上是,如果你认为有一段时间不是很久以前,这里很重要的TransactionSlip
小号是实际已发送各地的纸条通过马车。
但是,第二个模型实际上与现实世界银行的工作方式和现实世界银行软件的运作方式都匹配,这一事实并不能自动使它更“正确”。因为实际上,第一个(“错误”)模型相当接近银行客户如何看待他们的银行。对他们来说,transfer
是一项操作(必须填写表格),并且balance
是他们帐户对帐单底部的一条数据。
因此,很可能在高性能PS3射击游戏的核心游戏引擎代码中没有Rocket
类型,但是即使模型看起来很怪异,仍然会有一些世界的建模过程。给那些不是游戏机物理引擎编程领域专家的人。