概述
此文并非系统的说明如何用QT重构整个客户端,而只是粗算工期,给出一个时间概念
当前项目的优势
- 我们目前的人员配置都更熟悉VS开发。
- 目前使用的UI开发技术名为Sciter这相当于是基于html5+css的UI开发框架,自由度很大
痛点总结
1. 切换选择模型节点效率低
此处虽经历多次优化,但目前仍然不理想
因为根本的数据模型和业务逻辑很难改变了,主要问题在于引擎需要每次都经过分析生产一个json来描述属性组成,而客户端则需要分析这个json生成新的ui。而生成json,分析json,生成ui这三步都不是很轻的操作,综合就会效率低了。
改进策略:尝试参考AI模型训练算法, 我们可以考虑也训练算法。 比如我们点击同类型节点很可能生成的json实际上是相同的,只是参数不一样。而对于相同的json需要生成的ui也是一样的,也只是参数不一样。 但根据节点类型不同,确实有存在多种不同的json。 那我们是不是研究利用节点的各种特征形成一个特征码,来对应某一个json,某个ui页面,下次再遇到同样特征的的节点看看怎么简化生成json和生成ui的操作,特征码和json,ui都是通过用户不断的点击各种节点训练出一套东西,到时候我们打包的时候带上它,就能大幅提升性能。
2. 各个属性面板无法适当保持UI状态
目前我们的属性面板刷新后各种UI状态会丢失,比如滚动位置,折叠状态,输入框焦点等等,这在实际操作中会带来不便。比如滚动到某个位置编辑一个属性,之后想编辑另外节点的该属性,此时切换节点,面板会重置,导致还得重新找到这个要编辑的属性。
此处目前还没考虑好具体的解决方案
3. 引擎目前采用的回调模式有些混乱
对于客户端来说,用的最多的除了接口,还有就是回调,但目前只能指定一个回调函数,并不支持多注册,另外回调五花八门。 这种现象可以说是由于历史原因造成的,这使得当客户端和插件同时需要回调时,就很麻烦了,现在只好转发。
改进策略: 可以提供回调接口类,同时支持多注册,以及反注册这都是常规的套路了。另,回调接口要分类。
4. 目前UI遇到难定位的问题不太好调试
因为现在UI使用的html+CSS+脚本的方式,这使得调试起来并不是很方便。
改进策略: 如使用QT不存在这个问题
5. ANE模块如果方块数量很多的话效率低
这个模块由于现在使用的全场景绘制,如果说方块数很多的话,将会效率低下
改进策略:想一个策略使用局部绘制
6. UI缺乏综合设计
UI图标,字体,间距。。。等各种UI元素并没有一个统一的设计
改进策略:出原型,出设计,既然是2次开发,一定要有这两个东西,否则又是修修补补
7. 数据定义管理
现在有一个常见的现象,同个数据结构在引擎和客户端都有类似的定义,甚至有些枚举值也是如此,从而导致了一定程度的混乱
改进策略:该哪边定义的数据结构enum就由哪边来定义,注意引擎应该从来不需要知道客户端定义的数据结构。 但客户端经常需要知道引擎定义的数据结构
8. UI工程目录结构不够清晰
现在客户端各个模块代码文件目录结构不够清晰
改进策略:详细区分各个模块
9. 历史遗留
我们这个工程原生参考东西有点多,包括技术选型也是如此,有些东西都是过时的了,比如XTreme, 有一些UI风格也还是老的。
改进策略:该扔掉的东西就扔掉
10. 渲染窗口键鼠事件
现在渲染窗口的键鼠事件都是由UI转发的,这会使得代码看起来有点奇怪,出问题了也不知道责任在哪边。
改进策略:引擎不在依赖客户端转发消息,引擎自己去响应,客户端除了提供hwnd,不对该hwnd做任何消息映射。
相反的引擎可能会提供一个渲染窗口的专用回调,来提供一些事件给客户端用,比如showContext这样的。 总之要的结构就是,这个hwnd完全由引擎管理消息处理。
11. 插件和客户端过于耦合
现在客户端要负责通知插件各种事件,比如文件打开,甚至细分为文件打开之前,文件打开之后,新建文件 等等有好多,插件的目的本来是为了让客户端看起来更轻快一些,但这样一搞,客户端就被缠住了。
改进策略:客户端除非极特殊确实需要通知插件的,不在通知插件类似这样的事件,统一由引擎进行分发。比如文件打开,关闭这些引擎是知道的。
12. 插件管理有些混乱
现在我们客户端加载插件是通过遍历目录,查看dll构造来决定是否加载插件的,这感觉像是固定加载并不像是插拔的感觉。
改进策略:应该把我们客户端打造成带“插槽”的主机,而插件就像是可以插入这些插槽的外设,应可以随意插拔。 但实际上我们可能会设计成插件配置表,来加载指定的插件,可能不同的oem对应不同的配置表。总之不要把加载哪些插件的逻辑写在c++代码中。
最终目标为:所有的插件提供安装卸载能力,客户端有一个插件管理器页面可用于卸载已经安装的插件,但这个设计要求我们不要出现客户端必须依赖的插件。 比如你卸载了物理插件,客户端只是失去了物理编辑能力,但不会因此而无法运行,崩溃等等, 如果说是客户端必须实现的主要能力,就不要做成可安装卸载的模式,即便做成插件类型的工程,也不走可拆卸插件的套路和接口实现。
13. 太多固定加载的窗体
现在我们程序启动相当“累”,除了必须的初始化3d环境,还需要固定加载很多页面,这会导致启动变慢,甚至启动后有卡顿几秒,还有就是很多页面在多种需求下要求不能关闭,关闭只是隐藏, 关于这一点,我ui这边也有一个页面要求固定不能关闭,那就是场景树
改进意见:不要出现任何必须存在不能关闭的弹出窗口,dock pane,插件(尤其是它)。除非,除非实实在在没办法了。
14. 客户端文字编码不严格
现在客户端的char编码不够严谨,经过李帅改造可能已经好很多。
改进意见:当char作为要显示的文字时,一律使用utf8编码。QT从5.0开始, QString也会固定认为char*是utf编码
15. 目前我们的项目都只配置了Release编译选项
这可能导致发布版本的时候忘记开启编译优化,在一定程度上降低性能、但其实也有点好处,就是我们平时运行的版就是用户最终用的版,也确实遇到过Debug不出问题,relase出问题的情形。
改进已将:最好还是debug release两个编译选项都配置,开发期还是在debug下跑,发布在用release。
使用QT优势
通常VS和QT对比打架的时候,QT阵营的利器就是跨平台,但对于我们来说这个跨平台似乎只是锦上添花,目前重点还是windows。但用QT开发UI,除了跨平台还有一个好处,我认为也是最大的好处,那就是QT开发UI仍然算是与时俱进,尤其是开发我们这种大型工具类软件。
和脚本+HTML+CSS比起来,QT开发ui更容易调试,也更健壮,效率更高(效率其实主要还是看代码质量和策略),也有强大文档支持。
我们原来Dock Pane的开发是借助皮肤库XTreme, 而QT这方面是原生支持的,这个还是很有用的一个特性。
使用QT难点
目前我们的伙伴们,对QT的熟练程度不如VS高,有一定的学习成本。
但说白了客户端主要还是写功能逻辑,而功能逻辑VS和QT并无区别,无非是对QT的一些设计器什么的没VS那么熟练。
QT开发UI并没有HTML+CSS那么方便,虽然QT也有自己被称为QSS的东西,但和CSS比起来简直不堪大用,方便度也差很多,所以说呢,以前分分钟写出来的效果,用QT就得重载,写代码。举个简单的例子来说,假设我们要制作一个三态按钮,用CSS那就几个样式规定的事情,可以说一分钟就搞定了。但用QT你就得写代码,保守估计也得20分钟完成。这就是说用QT并不能使我们开发ui的工作变的更简单,相反的,会变的比原来复杂。
通常的控件,比如举例说的按钮并没什么问题,只是用QT会变的复杂一点而已
但至少有2个控件开发难度很大,当然这个在老工程里也是开发难度最大的2个控件
也就是动画控件和ANE控件,这俩控件用QT的话就只能完全使用自绘模式了,用html+css除了自绘还能利用很多东西,不细说了。 完全自绘复杂度会大幅提升,包括鼠标点击,键盘什么的,都得自己判断和响应。 当然带来的好处是,性能提升,如果能做到局部绘制,性能会大幅提升。
使用QT工期评估
概述:现在我们只能粗略估计,依照老工程从代码量,页面数量,可以预见的难点控件评估
1. c++客户端代码量
185个源码文件,行数:184477
重构估期: 5个月
2. 脚本文件
124个脚本和html文件, 行数:32366
重构估期:3个月
3. 页面数量(可能有遗漏,因为插件有的我不知道)
个数61 (这其中假如有tab切换到不同页面,实际上算成一个页面了,比如设置页面,渲染输出页面等等)
重构估期:3个月
4. 难点耗时控件
动画控件:1-2个月(包括曲线图,时间线)
ANE控件:1-2个月 (这个主要想实现局部绘制,难度不小)
虚拟场景树:1个月 这个可以说是咱们软件的一个轴心, 因为我们要支持超大数据,所以难点在于效率。
5. 15个插件重构
估期: 1-3个月 (这个主要看到时候是否能够同步进行, 相关开发人员是否都能分配进来)
6. 预留给策划和UI设计的时间
估期:3个月
综上
1年-1.5年