一些关于代码积累的记录

[toc]

当你需要新开一个项目时,往往需要从一些旧项目中拿走一些现成的框架,但这里的代码,如果没有好好管理,新开项目时往往要大费周章从旧有项目中剔除很多没必要的内容

如果将框架直接放在业务逻辑中,往往会出现一些开发者胡乱修改框架内容,或者图方便,在框架中添加了很多业务逻辑内容等

如果你的公司有多个团队,每个团队都各自实现一套基础框架、UI 框架等,显然是非常不合理的

UPM

在 Unity 推出了自己的包管理后,给框架管理带来了标准解法,将游戏中用到的框架内容,按照功能,逐个剥离,各自拥有独立的仓库

如:基础框架,UI 框架,寻路等,具体 Package 配置可以参考 Creating custom packages,现在的 UPM 基本上可以满足绝大多数开发需求了

按照功能划分的框架管理,可以严格的和业务逻辑进行剥离,也就是意味着,在一定程度上是一套通用的解决方案,而且针对不同仓库,可以分配不同的管理权限,可以有效避免开发者在写业务逻辑时,胡乱修改底层框架

现在采用这种方式管理框架的公司也越来越多,设计趋同

开始之前

在设计框架之前,我们至少要理清如下几个问题:

  • 通用框架要解决什么问题?
  • 什么内容有资格放进框架中?
  • 这种设计会不会给开发者带来额外的负担?

否则会造出一套不伦不类且不好用的轮子,接下来我们挨个分析这些问题

通用框架要解决什么问题?

通用框架很大程度上是在为公司后续的开发内容制定 统一的标准,如:事件怎么分发、资源怎么加载等等,通过有效的封装,可以严格限定每一种功能的调用方式,从而统一每个项目中业务逻辑开发时的思考方式

这样即使跨部门协调,因为 统一的标准,上手成本也是极低的

除此之外,通用框架还需要解决在不修改源码的情况下,给予外部 一定程度 的扩展性,因为要限制外部调用,所以我们大部分的 API 全部都是 Internal,此时还需要外部扩展,就需要借助友元来实现,[assembly: InternalsVisibleTo("xxx")]

这里只应该提供 一定程度 的外部扩展性,代码开发没有银弹,要记住,你不可能解决所有的问题,或者说,通用框架不应该解决所有问题

而友元的扩展方式,不过是一条需要制定的标准,而框架中所有的标准就代表了最终的学习成本

什么内容有资格放进框架中?

这个问题其实很微妙,有时候你在写业务逻辑时,发现有一个组件恰好在很多场景下是一个比较通用的实现,此时想要加入底层,作为框架自带的一部分

但当这种情景比较多时,你会发现,底层多了很多这种类型的组件,对于开发这个组件的人来说,从开始就知道有这个功能,以及应该怎么用,但是对于其他开发者或者其他项目来说,这个新增的组件无法第一时间让所有人知晓,或者无法满足其他项目的功能,而需要重复造轮子

所以,最底层的框架应当是非常保守的,不做任何多余的事情,除非这个组件非常有价值,可以参与到标准的制定中,才能考虑加入到底层框架中

这里的内容和不要给开发者带来额外的负担中也有重合的部分,因为新增一个组件,就意味着开发者需要理解并阅读部分这个组件的源码,这种场景就是不对的

这种设计会不会给开发者带来额外的负担?

理解这个问题,需要先解释一下这里的负担是什么意思。我认为这里的负担可以大致理解为如下两点:

  • 是否必须记得做某件事?否则一定会出错
  • 尽可能少的通用组件,业务逻辑在开发内容时,无需思考底层是否已经有了对应的实现

第一点是当前问题中,最重要的一点。对于设计框架的参与者来说,实现一个功能是相对简单的,但是难在应当选择哪种实现方式的过程上。往往同样的功能实现有很多条路可以选,但是一定要选不会让其他开发者犯错的路

比如,当实现资源加载时,一般来说大部分的实现都是谁加载了资源,就必须要记得释放,也就是 Load 和 Release 需要成对出现,但是!如果一件事忘记做就会无法正确运行,那么后面一定会出问题!即使这个开发者是你自己

那么正确的解法应当是,外部仅需要 Load,Release 是完全可靠的自动释放,如果你好奇这里的实现可以参考 Addressable 迁移 YooAsset

重要的永远不是怎么做,而是为什么要这么做

内网!内网!

每家公司会因为各种不同的原因,将公司的电脑与外部网络隔离,这样会对我们框架的整体流程带来一些意料之外的工作量,但大部分都是有解的

首当其冲的就是 Unity 官方的 Package,官方应该有如何在内网使用 Unity 官方报的解决方案,但是我们用的是另一种方法

我们可以把 Unity npm 缓存文件夹作为一个内网的 git 仓库,每次在外网下载,上传后,内网的开发者自己 pull 一下即可,此处 Package 在检查包时,会首先看 npm 缓存文件夹中是否已经下载了,利用这个机制可以较为可靠的解决这个问题

OpenSSH 标准的 ssh 管理

一般来说,公司的 git 仓库都不应该允许 http 的方式对仓库进行操作。而 Unity 对内网仓库的拉取是遵循 OpenSSH 标准的,所以需要在本地配好对应的设置,让 Package Mananger 在拉取内容时,可以有效的通过 git 仓库的认证

下方为 ~/.ssh/config 文件中的配置参考

Host yourgit.com
Hostname yourgit.com
IdentityFile ~/.ssh/privatekey
User yourname

Tips: 很多人在选择 git GUI 客户端,尤其是 Windows 用户,特别偏爱小乌龟,而且在生成 rsa 秘钥时,非常喜欢用 Putty 这个软件, Putty 的秘钥是不符合 OpenSSH 标准的!

如果你也是使用这种方式进行的秘钥配置,强烈建议你换掉

最后

整个公司框架的维护和编写,是软件工程这门学科的具体体现,实现的过程中一定会曲曲折折,偶尔也会出现自己跟自己左右互搏的情况,但是在你开始写每个组件之前,做好相应的思考,应当会走的更平坦一些

因为框架是给公司所有人使用,请一定记得在每处修改的地方留好 详尽 的注释,解决了什么问题,为什么要这么解决等等,一定要 详尽,这里的注释不仅仅是写给别的开发者看的,也是写给未来的自己