在Unity中拥抱响应式编程(二)

本文探讨了数据和代码分离在DO中的应用,强调了如何通过这种方式增强代码复用性和测试性,避免继承和组合带来的复杂性。通过C#示例,展示了如何将数据和行为分开,以及它在Unity中的实践。同时,讨论了可能的数据竞争问题和性能影响。

第一原则

在本篇中主要介绍数据和代码分离这一概念。此概念属于面向数据程序设计(DO),就是要打破面向对象设计(OO)中关于 封装 (将代码和数据都放入一个对象中)的概念,将有状态类( Stateful class )转换成无状态类(Stateless class),从而增强代码复用性或者解耦。

分离的好处

  • 增加代码在不同上下文界限(Context)中的复用性
  • 越独立的代码越容易测试
  • 降低系统的复杂性

好处1.增加代码复用性

DO如何复用代码

在OO中,通过继承和组合来复用代码。当继承与组合越多,系统变得更加复杂。

OO如何复用代码

在DO中,以C#为例,我们将数据放入数据块类中,方法整合进静态类中,然后将数据块作为方法参数传入,如下所示。
    
public class PlayerMoveData { public Vector2 velocity ; public float jumpForce ; } public static class PlayerMoveModule { public static void PlayerMove ( PlayerMoveData data ) { //... } public static void PlayerJump ( PlayerMoveData data ) { //... } }
这个代码片段目前没有太大意义,因为缺少重要的上下文界限(Unity环境),但有助于理解分离的概念。在接下来的篇章中,我会详细阐述这些代码在Unity中是怎样运行的。

好处2.更加容易测试的代码

现在假定我们有一个需求,玩家速度越大弹跳力越高,需要测试: 当velocity=(0,10)时, jumpForce = 5 ? 为此,编写如下测试代码。
    
public void VelocityInfluenceJumpforceTest_velocity10_jumpForce5 ( ) { //Arrange var data = new PlayerMoveData ( ) ; //Act PlayerMoveModule . PlayerMove ( data ) ; //Assert expected = 5 ; actual = data . jumpForce ; Assert . AreEqual ( expected , actual ) ; }
如果将代码和数据都写入Player脚本中,并继承Mono类。因为不能实例化Mono类,测试难以进行。

好处3.代码更加易懂但却有代价

虽然面向数据有其好处,但却有不可忽视的代价:
  • 数据对所有代码来说都是可见的
  • 性能问题。面向数据认为数据是不可变的,每次对数据的修改只是创造了一个拷贝,但是这样会造成大量无用的旧数据沉积。在上面的例子中,我没有做拷贝操作,而是直接修改,可能会造成数据竞争问题。但是我认为这种可能性很小,因为Unity是单线程环境,造成数据竞争的概率很小。
  • 数据竞争(Data race),两个不同代码片段同时修改同一个数据,造成数据竞争。
参考资料 Yehonathan Sharvit, Data-Oriented Programming
评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
红包 添加红包
表情包 插入表情
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值