大家给了非常多的建议和想法, 我稍微整理了一下做一下总结
模块设计 + import
好处:通过 import 加载关联模块,不依赖文件命名和加载顺序,不会因文件改名/混淆加载顺序改变无法正常运行
坏处:容易循环依赖,导致模块设计要尽可能独立,这可能导致想用其他模块现有功能只能复制粘贴,或者把代码写到一个可能混杂很多函数的中间模块里.想要模块清晰好用会考验设计,不然可能开发新模块或扩展已有模块功能时改变了依赖顺序关系 发生循环依赖,就不得不花精力修改
全局写入
好处:能避免循环依赖,一些人在typescript有模块这个机制的情况下还是选择要写全局大概就是不想费精力解决循环依赖,尤其是个人开发
缺点:强依赖文件的加载写入全局顺序,文件改名或者混淆名字后顺序变了会导致程序直接无法运行.cocos并没有能保障文件加载顺序的机制 (用A开头命名文件作为程序入口 import 其他模块控制这个做法很不靠谱,随时可能出问题),将游戏内所有文件都指定import顺序这个做法费时费力不通用,漏掉会成为隐患
最后我想了一种方法,既能保证模块不受文件加载顺序影响,又能避免循环依赖问题
我以 onLoad 为分界
onLoad 前注册的模块写入到一个 临时变量里 禁止写入 全局
onLoad 后 将 临时变量里 的全部模块注册写入全局
这样
onLoad 前没有任何写入全局变量的行为,走的完全是typescript模块的加载依赖机制,模块初始化用到其他模块的功能就必须import,这能保障游戏运行与文件加载顺序无关
onLoad 后所有模块写入全局,所有模块都可以全局访问到,调用函数依赖的模块 不需要 import,这样就能实现 ArrayUtil 的 sortRandomOrderBySeed 这种函数可以放心大胆的使用 RandomUtil 的封装好的功能, RandomUtil 的 choiceElemByWeight 这种函数可以放心大胆的使用 ArrayUtil 的封装好的功能,不需要互相大段复制对方的代码,也不需要改代码时逐个模块找代码去改
缺点就是因为所有模块都注册全局了,只能依赖cocos编辑器报错知晓哪个模块初始化依赖了哪个模块
至于 像 初始化 某个常量对象,比如初始化 EncryptKeysConst 时 import 了 EncryptUtil , EncryptUtil 用到了 ArrayUtil 的函数 这种情况, 由于 发生在 onLoad 前没有全局写入 , 所以 间接访问 ArrayUtil 会失败
这种情况 EncryptKeysConst 虽然没直接依赖 ArrayUtil,但是模块内间接用到了,这种我就封装一个临时写入 全局的函数 ,在 EncryptKeysConst 模块退出前再把临时全局的模块再删掉(不删下次临时写入或onLoad会有错误警告) .这样 模块加载完成后 全局环境还是没有被写入东西的 ,就不会影响到下一个模块的加载,也不会因为加载顺序变了 代码时好时坏
目前我试了下,这办法似乎可行,虽然有 依赖编辑器报错才知道模块初始化有依赖 这个明显缺点
但它免去模块用功能要复制粘贴其他模块代码,或者把各路代码都塞入一个中间模块 这种苦恼.自己封装好的函数却得考虑模块依赖关系不敢随便用, 或者设计不当 循环依赖 不得不花精力重新设计模块
也不用担心文件加载顺序变了程序直接无法运行,因为 onLoad前还是严格遵循 typescript 的模块加载机制,只是 onLoad 后做了解耦
不知道大家有没有其他好的想法