TableCraft is finally here!
TableCraft is finally here!
TableCraft 发布!
从21年起经过两年断断续续的开发,TableCraft终于发布了v1.0.0版本,并开始提供给项目组同事使用了。这篇文章会介绍从最初立项到最终发布TableCraft的设计发生了怎样的变化,TableCraft现阶段存在的一些问题,以及未来的发展目标。
起始
开发TableCraft的初衷是为了让自己能从手写读表代码的痛苦中解放出来:重复而机械的工作,除了徒增出错的风险没有任何意义。
在这几年的项目开发过程中,程序组也出于缩短启动时间,减少解析配置表的内存分配、内存占用,推进过几次读表代码的优化,如多线程读取解析,csv格式配置转为binary格式。概括下来,手写读表代码除了累人,自行实现的读表代码提供了过高的自由度,还会带来额外的问题:
- 不同配置表中相同数值类型字段的读取行为可能不一致(空字符串代表false?true?),配置负责人难以形成习惯,配置错误风险高。
- 将csv格式转换为binary格式可能丢失部分信息,使得难以生成、甚至无法生成对应的binary读表代码。
- 不同的配置表之间可能存在依赖,使得多线程优化工作难以展开。
- 开发者自身水平问题导致读表代码效率差,资源占用多。
同时正所谓由奢入俭难,在先前项目组体验过多端一致(C++,C#,Lua,应用于客户端运行时,客户端编辑器,服务器)的配置表读取库,与配置表编辑、代码生成工具后,每次手写读表代码都是一种煎熬。于是在21年末的一个稍稍有空的周末,TableCraft的开发工作开始了。
经由
TableCraft最初的设计构想如下:
- 兼容常见的配置文件格式
- 为配置文件设计元数据文件,补全生成读表代码所需的描述信息
- 提供读表代码的文本形式模板(Template)文件,而不将读表代码内容硬编码到工具中,目的有:
- 工具可跨项目组使用,减少重复开发工作量
- 考虑到读表代码发生改变的频率较高,将代码模板化可以减少重复编译
- 将配置文件与元数据文件、代码模板文件结合,生成各种语言的读表代码
- 提供单独的library文件,可开发命令行脚本用于构建任务,也可开发图形化工具用于日常开发使用
有了基本目标之后,21年末就着手以C#进行核心dll的开发(也就是这时我发布了 关于配置代码生成器的构想),但卡在了两点上:
- 若要实现读表代码模板化,意味着需要设计自己的模板语法,以及模板文件编译器;虽说不至于无从下手,但工作量比预期的大很多。
- 对使用什么GUI开发框架没有下定主意,当时甚至想过使用ImGUI
由于项目组的工作也繁忙起来,TableCraft的开发工作就暂且搁置了。但现在回想起来,也庆幸当时及时停手了,才能在后来找到更为成熟的解决方案。看来有些时候闷头干活真的不可取,放下执念,沉下心学点东西才是卓越之路啊。
23年在写博客的时候发现,支持markdown格式的博客框架其实都应用了类似的模板(Template)技术,使用用户提交的markdown文本,根据一些预设好的规则,来生成出最终的静态html页面。这时候我才意识到,搜索的关键字应该是模板(Template)。
果不其然,.NET 中也有类似的解决方案,称作 T4 Text Template,也不是什么新鲜技术了,甚至在开发时还是借用了第三方库才实现了兼容 .net6。
而GUI框架的选取上,则是采用了项目组前辈推荐的 Avalonia UI。现在回想起来,其实应该从WPF开始体验的好,直接入手 AvaloniaUI 可能缺失了一些比较的过程,不过不得不承认选取AvaloniaUI 大大提高了开发速度。
最终,TableCraft以这样的形式呈现了出来:
- 核心库 nuget: TableCraft.Core
- 核心库 github page: TableCraft.Core
- 基于Avalonia的可视化编辑器 github page: TableCraft(Editor)
缺陷
在TableCraft正式投入使用的这一段时间内,对工具的反思也在持续进行中。
从具体实现的角度,TableCraft存在以下几点问题:
- 受游戏开发经验的影响使用了LitJson库,实际上对于现代的.net 应用开发,使用标准的Newtonsoft.Json会更好一些。
- 配置文件分散且配置方式比较原始。
而从设计思路的角度来看,TableCraft可能存在一些更严重的问题:
- TableCraft不可避免地硬编码了配置表元数据的json格式,对于使用工具的用户来说,了解并使用此json格式是不可避免的。如果出现目前元数据不能满足的需求,实际上还是根据项目的需求扩展 TableCraft.Core。
- TableCraft虽然设计了数据源文件(Source)以及描述文件(Decorator)的接口类型,但实际上若要支持新的文件类型,还是需要额外的开发量,这也是很难避免的。不同项目所需要的支持的文件类型可能不同,理想情况是可以使用插件形式来做支持,如果做成 all-in-one 就有些臃肿了。
- T4 Text Template 并不是普及度很广的解决方案,虽然可以使用C#进行编码,但有一定学习成本。并且即使是在IDE里进行编写Template(.txt)文件,体验也比不上直接编辑源文件。这点可能会对模板文件的维护带来负面影响。
结合上述问题看,对于一个没有任何现成解决方案的新项目开发组来说,如果对硬编码读表代码没有太大抵触,自行设计元数据格式,并自行开发配置文件编辑器,生成读表代码,实际上工作量也不比使用TableCraft大多少。而实际上,配置解决方案在同一开发组/公司的项目间一般都会进行流通,所以相信大多数新项目也都会有现成的解决方案。
所以TableCraft的完工虽然可喜可贺,但考虑到上述问题,想要看到TableCraft“流行起来”可能还是有相当难度的。但或许也正是完成了TableCraft,才让我意识到了上面这些问题,从这个角度来看,23年的上半年也可以当作是没有白费了。
展望
那么TableCraft是否还会有新内容上传呢?答案是肯定的,虽然时间上给不出什么保证(笑)。接下来我将目前能想到的一些可以开展的工作记录在这里,会按照实现成本从低到高的次序排序:
- 考虑到未来配置表的数量可能会变得很多,配置表浏览列表和字段浏览列表会新增一个搜索框。
- 会在TableCraft中新增一个弹出窗口来配置appsetting.json中的内容。
- 版本控制相关更隐私的账号密码内容可能还是写进注册表的好。
- 如果要做成看起来更完善的工具,考虑用installer的形式来安装,还需要工具的发布与更新检测。
最后要补充的一个内容也是来自日常工作中的体会:在这几年的工作中没少听策划同事关于配表的抱怨,实际上在需要让配置表满足多环境、多地区、多用途需求的情况下,想要减少重复配置量、减少配置错误属实是很困难的一件事。
在这种环境下,经常会诞生出很多奇怪的配置表机制,例如配置表的其中一列是比特位,此行仅在特定地区、特定环境生效;或者在某某条件下,一张小表能够合并到原先的同名大表中;在某某条件下,去读A路径的配置表而不读B路径的配置表。
因此,配置表编辑器的开发看上去就非常必要了。设想中的配置表编辑器应该有这些功能:
- 字段类型检查。类型检查是减少配置问题的重中之重。
- 主键和外键。数据库中的概念在这里依然有用,使用外键更好地支持配置表的跳转与KeyExist检查。
- 配置表的声明,同时创建元数据进行描述。一个“配置表”不再与一个文件一一对应,而是一组文件的抽象:可以是不同环境(客户端,后台服务器...)下的配置表,也可以是同意环境下不同地区的配置表。
- 原型模式的支持,即可声明基于配置表A的配置表B。配置表B的数据是基于A的增删改,配置表B只需要编辑改动,也只储存改动数据。而在Build阶段后,运行时,配置表B将有基于A的完整配置数据。
- 配置数据的导出。有了上述的配置表元数据描述这就很好办了,运行时要用csv,json,binary都可以。
不过自然,开发这些功能也要不少工作量,也不是可以不和项目组沟通一个人闷头做的,所以目前也只停留在“想想而已”的阶段。或许未来在一些别的项目组干活会发现他们已经有现成的工具了呢(我觉得是应该要有的)。
那么这篇文章也就到此告一段落啦,希望我们不久后还会再见!
2024新年快乐!