我们已经解读的Pixonic DevGAMM Talks的下一份报告有点哲学意义-这是康斯坦丁·格拉迪雪夫(Konstantin Gladyshev)的演讲。 他是1C Game Studios的首席游戏程序员,并谈到了在整个产品而不是单个功能的上下文中管理开发复杂性的原理。 通过示例,他展示了为什么开发的主要目的是确定不应执行的操作。 有关其他报告,请阅读文章末尾的链接。
我想谈谈北方,但决定就应该做些什么做一个哲学报告。 我曾在《邮政III》,《坚不可摧》,《战争机器人》上工作,目前正在做口径,这是来自1C和Wargaming的在线射击游戏。

我们为什么决定谈论KISS(保持简单,愚蠢)? 因为即使是具有20年经验或CTO的年长者,也经常会继续雕刻和发明一些东西。 但是您需要更轻松地做。 实际上,关于YAGNI的更多信息(您将不需要它)和一些哲学。
我必须马上说,我们不是在谈论完全愚蠢的解决方案,例如“查找x”,而是在谈论或多或少的简单解决方案。

为什么有时太难了? 一切始于良好的意愿,正如您所知,它们会导致地狱。 这是关于这的漫画。

其原因大致相同,但我称它们为不同的原因:
- 通用解决方案 。 有某种功能,我们立即从中建立一个库,再增加一百万个案例。 然后我们的射手突然变成了农场? 或“下一次我将再做一个完全相同的射手”。 它不太可能会为您改变。
- 未来的证明 。 几乎一样-这些都是不存在的问题。 “如果我现在有一百万用户,我是否需要承受22台中间服务器?” 等 要开始赚钱,一台服务器就足够了。
- 使用错误的工具 。 当您使用不适合并持续存在的工具时。
- 每个人都知道过早的优化 。
当他们制作口径时,我们有一个例子。 然后,帮助我们的家伙决定立即在最新的C ++中制作一个超级序列化器。
结果,它不能按预期方式工作,发送局部状态很不方便,因为模板无法真正理解需要的地方,不需要的地方,或者您做出一些标记。 样板代码中的错误,甚至作者随着时间的推移也不了解。

然后,一位程序员在短短两个小时内将所有这些内容重写到了一页C代码中,这正是我们当时所需要的。 而且效果很好。
另一个例子。 我们有邮政III,它是在Source引擎上制作的。 有这样一个开放的世界,您可以在地图之间行走,使用第三人称摄影机,许多带窗户的美式单层房屋,机器人可以四处奔跑和恐慌开门。 结果,整个BSP无法正常工作。 它被考虑了很长时间,因为窗户使它变成一百万个扇区,却什么也没做。 它占用了大量内存,并且加载了很长时间。

制造引擎的《半条命》是第一人称射击游戏,从第三人称射击就很不方便。 《半条命》中有用的一切都不适合我们。 另外,由于需要第三者攀爬,所以应该进行大量动画处理。 有必要更换发动机,但随后别无选择。
当一切都不好,很困难但又把我们推的时候该怎么办? 首先,以正确的顺序进行功能,因为提前优化是问题之一。 有些人在缝制衣服之前就开始粘上条纹,然后再缝制,因为条纹干扰了。
首先,制造最简单的芯片,使其能够正常工作,然后稳定下来,然后进行优化。 正是按照这个顺序,其他所有事情都是错误的。

通过可视化,我们了解到它是最低限度的操作,即 MVP(最低可行产品)。

然后您评估其潜力。 假设游戏设计师想出了一些功能,程序员求助于他们,并说:“我会做的很好,我不会做的不好,所以请立即进行时髦的游戏设计。” 但是他怎么知道? 他没有参加比赛,也不知道是好是坏。 因此,理想情况下,您可以制作一个功能,正常播放后再做。 不正常-丢出去,可惜。
一千多年前,孙子曾说赢得100场战斗不是高峰,没有战斗就是胜利。 即 不要做你做不到的事情。
稳定。 您已经制作了功能,并在没有不必要的添加的情况下进一步稳定了它。 您是否需要在树上的轮子或绳索上的轮子? 它挂了。 没什么

因此,如果突然发现(没有任何未来证据)该功能应更改-请重新开始。 只是制作原型,稳定下来,不要试图猜测。 您仍然不会猜测。
好吧,过早的优化。 这总是不好的。 您最终需要进行优化,当您确定该功能很重要时,就应该对其进行优化,并且在不久的将来它不会发生根本性的变化。

因为优化是一组特殊情况。 通常,代码的可读性恶化,抽象破坏和可移植性也大大恶化。

这是一张挑衅的幻灯片,因为拐杖真的很糟糕。 但是这里显示的情况是,有许多乏味的功能和原型,一切都很糟糕,而且似乎一切都会崩溃。 但是事实并非如此。 看-这是模板,将混凝土倒入其中,而干燥时支撑着“拐杖”。 即 这种情况绝对是正常的,然后将“拐杖”拆除,但不会立即消除恐慌。
简要介绍哲学。 没有普遍有效的解决方案。 不要尝试在所有情况下都提前100年创建框架。

最好制作很多能很好地完成工作的小件。 尽快扔掉不必要的东西,不要试图去支持它。 并且在编写代码时,使其明确。 有时,最好编写出用手序列化的显式代码,而不是反省或进行其他操作。 在不需要时使用依赖操作也是一个坏主意。 很难读取,只有运行时错误的一半。 显式胜于隐式。 并使其尽可能简单,以免在某人不了解某件事或什至完全忘记某件事时出错。
正如李小龙(Bruce Lee)所说,简单是最高的艺术水平。 曾经由他教过Jeet Kune-Do的演员问他:“您的武术Jeet Kune-Do的本质是什么?” 在那一刻,李小龙放下钱包,演员把它捡起来,李小龙说:“你看,你弯下腰拿起钱包,如果你站在一个骑手的姿势,做成kata,那你永远不会提起它。”
听众的提问
“您说过早的优化是邪恶的。” 在项目刚开始时是否值得编写过早的测试?-据我了解,一切过早都是有害的。 在测试方面,我不是很坚强,因为在游戏开发中(在许多情况下)测试接近开发的终点。 在一开始,一切都改变得如此之快,以至于您在编写测试时,游戏设计师就已经改变了一切。 我认为,花精力去测试两个小时内将发生的变化是不好的。 这必须在稳定阶段完成。 但不是在原型阶段。 但是如果团队可以快速编写测试,那可能很好。 如果没有,那就没有。
-您提到拐杖将被移除,但是有一个很棒的论点-没有什么比临时的更持久。 我们所有人都从事游戏开发,有截止日期,制作人,然后有新功能,等等。 您多久见一次清洁拐杖的情况? 他们把它们归零了吗?-可能不是零。 如果该项目正在进行中,您将总是有些拐杖。 如果对它们进行系统地清洁,那一切都会起作用。 即 您做了一个功能-立即记录。
-就是 公司应该建立某种流程吗? 正式的拐杖清洁阶段类型?-是的,我认为这应该包含在任务中。 即 如果您需要在任务过程中进行重构,则可以进行重构。 粗略地说,重构这个词也不是-它在任务内部。
-您在实践中做到了吗? 您来到生产者,并说要计划新的迭代,我们需要两周的时间来清理,重构等。 他说业务价值为零,现在我们使用x,然后在下班后的晚些时候将其清理。 在这种情况下怎么办?-我们成功了。 生产者知道有些债务需要及时纠正。 不是您有一个新版本,就不是一个新功能,而是一种重构。 只需选择合适的生产商。
“有了经验,理解就来了,越简单越好。” 但是,新手程序员尝试创建复杂,可怕,庞大而庞大的系统。 问题:除了强硬的“否”之外,如何避免他们这样做?-我认为这是一个学习问题。 有必要尽早显示哪些解决方案有效,哪些无效以及为什么。 如果您有经验,可以解释为什么不需要这样做,则可以举很多例子,它已经很好地发挥了作用。 用您自己的示例展示并不断监控,以使一切变得简单。 放置原型,以便它们更频繁地重写-当您经常重写时,您不会觉得写太多,而他们会写得越来越简单。
-如果已经在多个项目中使用了非常复杂的东西,而这种复杂性不再有用,而是会产生干扰-切换到简单解决方案有多容易?-我的想法是,重新开始。 理想情况下,是一个从头开始的独立团队。 您很可能会很快恢复80%的功能。 在新的干净库中。 然后您会追上。
-例如,有一些功能强大的序列化器和游戏逻辑编辑器,现在已经过时了...-这些都是不便的工具。 放心吧。 例如Unity。
-告诉我,您在代码中的计划是什么,它有多详细? 主程序员是否解决所有次要问题,所有任务?-我们有这种无政府状态,结构相当平坦,人不多。 我们相信每个人,只需分配谁将采用原型,谁不采用。 可以是任意人。
通过Pixonic DevGAMM进行更多对话