从属于杂项.html

重构思考一

前言

目前是大一的学期末,我在期末备考的时候审视了我这学期写的一个大型项目SimpleMeters,SimpleMeters这个项目的存在本意是我帮助入门VST3的,从4月份开始我一边学习c++一边做一个项目,但是开始做项目我没考虑到多人协作,目前也没有多人协作,所以项目的设计模式和设计原则都是凭感觉,项目没有大问题,但就以我目前的角度而言,我一开始也不会想到这个项目会发展得这么大,一开始只是想用这个项目练习一些音频处理工作,同时我并不推荐一位新手上来就写这种大型的项目,原因我会一一列举

1.不了解当前主流的项目架构

刚刚说过我是一个新手,所以像什么《设计模式》这类书在一开始我是完全没有接触过的,而这就会导致开发时我脑子中并没有可供选择的架构,没有可选择的架构同时也就意味着没有对架构的优劣势和各个架构的配合,同时对于项目未来的架构发展没有清晰的构想。列举我项目中出现的一些问题,第一个就是单例滥用,第二个是ui和某些业务逻辑耦合,还有其他一些我暂时无法列举,这些虽然算不上大问题,因为我不考虑和其他人合作,当然可能是我本没有把这个项目当成能一直写并可拓展的项目,不过现在我会尝试重构代码,重构代码也是一项极其花费时间的操作。我要重点强调一下,直到我写下这段文字的时候,我仍然没有清晰的了解为什么单例是一种“反模式”,这也就引出了下一个问题——开发原则

2.原则约束的问题

我在这里来说一下SOLID原则,因为前面的单例严重违反了该原则中的一些条目,作为一名新手,即便是没有接触过使用单例遇到的问题,没有从代码实战层面上认识到为什么单例是一种反模式,如果在开发早期就有意识地遵循 SOLID,仍然可以在很大程度上避免使用单例,减少后期重构的工作量。我以后可能会单独说说单例究竟违反了哪些SOLID原则以及尽量不使用它的原因。话说回来,既然SOLID原则能被业界经验丰富的大师总结,这就足以说明一个程序员被该原则约束,一般都能写出易维护和拓展的代码,新手一开始无法了解原则,这也会导致之后的重构

3.安全问题

我第一次接触到std::optional、std::unique_ptr这类管理生命周期的标准库工具,是在写下这段文字前的两个月,不得不说我这几个月学习的东西太多了。即使我建议新手别上来就写这种大型的项目,你还是可以在各种错误中学习和认识到内存安全有关的问题,比如说所有权问题,前提是有一点——你的项目写完后不管,写完就扔。虽然我一开始就没想过写这个项目这么久,不然之后需要偿还的技术债是不得不还的,这就包括了刚刚说到的架构问题。如果我一开始就掌握内存安全和线程安全的知识,我是不是就能在选择架构时头脑能更清晰,如果一开始就掌握内存安全知识,在使用 std::shared_ptr 时就可能会多问一句:是不是当前架构或实现本身就有问题?同样,当你去修改,增加,删除代码中某些功能时需要思考很久,这是不是也是说明当前代码架构或实现有问题?这是我写这段文字时想到的一个问题

4.测试问题

对于我这个新手而言,测试目前它不存在我写代码的标准流程当中,然而测试是写出健壮代码的前提之一,所以这是一个仍需新手学习的内容

5.错误处理

如今项目中没有任何一行错误处理的代码,这也是我作为新手的问题之一,如何选择错误处理的模式和如何处理错误也是一个需要学习的内容

6.学习和项目的平衡

到现在,我发现我缺乏完整的知识体系,我大一下这一个学期把太多的时间花在了写这个项目上,本身有点忽略学习的知识,只是遇到问题后才能学习一下。之前提到,没有了解当前主流的项目架构,就无法比较架构间的优劣势。一个完整的知识体系,不仅节约在架构上思考所花费的时间,有些仅凭自己感觉的架构并不一定是最佳实现,毕竟人的想法和时间都是有限的

这就是我为什么不推荐一位新手上来就写这种大型的项目

重构的方向

目前有一些需要重构的点,一个是单例滥用,最大的问题是:我用单例管理所有组件,导致整个插件只能存在一个全局状态,无法支持宿主同时加载多个实例,这从根本上违背了 VST3 的设计。第二在paint里分离绘制代码和绘制的具体业务逻辑,比如说将RMS的大小对应什么样的颜色的代码分离出来,使用策略模式。第三完整考虑组件的析构顺序,保证内存安全。第四错误处理,目前项目中存在一个交换双指针缓冲的机制,需要考虑到卡顿的情况,比如读取时写指针切换回来了,这个需要进行错误处理而不是崩溃,但我想到了一个更好的办法理论上可以完全避免这个问题。可以发现前面积累的技术债都在这里以时间的形式体现出来了