最近接手了一个AI可穿戴设备的项目,代码质量可以说是惨不忍睹。各种硬编码、重复逻辑、命名混乱、耦合严重,改一个地方要牵动好几个文件。

我花了两周时间,对这个项目进行了一次彻底的重构。从最开始的无从下手,到最后代码变得清晰优雅,这个过程有很多收获。这篇文章我想分享一下这次重构的经历,聊聊AI可穿戴设备开发中的代码特点,以及我是怎么一步步把烂代码变成优雅代码的。

项目背景

先说说这个项目的背景。

这是一个AI可穿戴设备的配套应用,设备是一款智能手环,能采集用户的心率、血氧、运动数据等,然后通过AI算法进行健康分析。应用端负责和设备通信、展示数据、提供健康建议。

这个项目已经开发了两年多,前前后后换了好几拨人。每个人都在上面加了一些功能,但很少有人做重构。代码就像滚雪球一样,越滚越大,也越来越乱。

我接手的时候,项目已经有十几万行代码了,但结构非常混乱。很多功能是赶工期的时候写的,能跑就行,根本不管代码质量。

烂代码长什么样

先描述一下这个项目的烂代码有多烂。

第一个问题是文件巨大。有一个主控制器文件,居然有三千多行代码,什么功能都往里塞。设备连接、数据解析、UI展示、业务逻辑,全在这一个文件里。想找一个功能,要翻半天。

第二个问题是重复代码。同样的设备通信逻辑,在好几个地方都有实现,而且实现方式还不一样。有的地方用回调,有的地方用代理,有的地方直接写死了。改一个通信协议,要改好几个地方,还容易漏。

第三个问题是硬编码。设备的命令码、数据格式、阈值参数,到处都是硬编码的数字和字符串。比如"0x01"代表心率数据,"0x02"代表血氧数据,这些魔法数字散落在代码的各个角落。

第四个问题是命名混乱。变量名有的用拼音,有的用英文缩写,有的随便起个名字叫a、b、c。函数名也是,有的叫handleData,有的叫process,有的叫doSomething,根本看不出是干什么的。

第五个问题是耦合严重。UI层直接操作蓝牙通信,业务逻辑直接更新UI,各个模块之间你中有我、我中有你。改一个UI,可能会影响设备通信;改一个通信逻辑,可能会导致UI崩溃。

第六个问题是没有测试。整个项目几乎没有单元测试,所有的测试都靠手动。改完代码,手动跑一遍,觉得没问题就上线了。结果经常是改了A功能,B功能出了bug。

这样的代码,维护起来非常痛苦。每次加新功能,都要先花大量时间理解旧代码,然后小心翼翼地改,生怕改出问题。

重构的思路

面对这样的烂代码,我没有急着动手,而是先想清楚重构的思路。

我的重构思路是:先理解,再分层,后优化。

第一步是理解。我花了三天时间,把整个项目的代码通读了一遍,画了架构图,理清了各个模块之间的关系。虽然代码很乱,但核心的业务逻辑还是能梳理出来的。

第二步是分层。我按照职责,把代码分成了几层:设备通信层、数据处理层、业务逻辑层、UI展示层。每一层只负责自己的事情,层与层之间通过接口通信。

第三步是优化。在分层的基础上,逐步优化每个模块的代码,消除重复,统一命名,增加注释,补上测试。

重构的过程中,我遵循了几个原则:

第一,小步快跑。每次只改一小部分,改完就测试,确保没有问题。不要一下子改太多,否则出了问题都不知道是哪里改的。

第二,保持功能不变。重构的目标是改善代码结构,而不是改变功能。在重构过程中,要确保对外的行为不变。

第三,随时可以回退。每次重构前,都提交一次代码,这样如果改出问题,可以随时回退。

第四,边重构边测试。每改完一个模块,就跑一遍测试,确保没有引入新的bug。

重构的具体步骤

说说重构的具体步骤。

第一步,提取设备通信层。

设备通信是整个项目的基础,也是最混乱的部分。我把所有和蓝牙通信相关的代码,都提取到一个单独的模块里。这个模块负责设备的连接、断开、发送命令、接收数据,对外提供统一的接口。

以前,各个地方都直接操作蓝牙,现在都通过这个通信模块来操作。这样,通信协议的变化,只需要改这一个地方就行。

我还把所有的硬编码都提取成了常量。比如命令码、数据格式、超时时间,都定义成了有意义的常量,不再用魔法数字。

第二步,建立数据模型。

以前,设备传过来的数据,都是用字典或者数组来传递的,字段名不统一,类型也不明确。我建立了清晰的数据模型,比如心率数据、血氧数据、运动数据,都有对应的结构体或者类。

这样,数据在各个模块之间传递的时候,类型是明确的,字段是统一的,不容易出错。而且编译器能帮你检查类型错误,很多bug在编译阶段就能发现。

第三步,拆分业务逻辑。

以前,业务逻辑都混在控制器里。我把业务逻辑拆分成了独立的服务类,比如健康分析服务、数据存储服务、推送服务等。每个服务只负责一块业务,控制器只负责调用服务和更新UI。

这样,控制器变得很薄,只负责协调,不包含具体的业务逻辑。业务逻辑都在服务里,方便测试和复用。

第四步,优化UI层。

UI层以前也是一团糟,一个页面里有大量的业务逻辑和数据处理。我把UI层也做了优化,用MVVM的架构,把数据和逻辑放到ViewModel里,ViewController只负责视图的展示和用户交互的响应。

这样,UI代码变得很清晰,每个控件的状态都由ViewModel来管理,不容易出现状态不一致的问题。

第五步,消除重复代码。

在分层的基础上,我开始消除重复代码。把重复的逻辑提取成工具函数或者公共组件,比如日期格式化、数据校验、错误处理等,都放到了公共模块里。

消除重复代码之后,代码量减少了很多,而且维护起来也更容易了。以前改一个逻辑要改好几个地方,现在只需要改一个地方。

第六步,统一命名和风格。

我对整个项目的命名做了统一。变量名、函数名、类名,都按照统一的规范来命名,做到见名知意。代码风格也做了统一,比如缩进、空格、括号的位置,都保持一致。

统一的命名和风格,让代码的可读性大大提升。新人接手项目,也能很快看懂。

第七步,补上单元测试。

重构的最后一步,是补上单元测试。我为核心的业务逻辑和数据处理模块,都写了单元测试。这样,以后再改代码的时候,跑一遍测试就能知道有没有改出问题。

有了测试之后,重构的胆子也大了。以前改代码总是提心吊胆,现在有测试兜底,放心多了。

AI可穿戴开发的特殊挑战

在重构的过程中,我也体会到了AI可穿戴设备开发的一些特殊挑战。

第一个挑战是设备资源有限。可穿戴设备的计算能力、内存、电量都很有限,所以代码要特别注意性能和功耗。不能用太复杂的算法,不能有内存泄漏,不能太耗电。

在重构的时候,我特别注意了性能优化。比如,减少不必要的计算,复用对象,避免频繁的内存分配。这些优化,让应用的运行更流畅,也更省电。

第二个挑战是蓝牙通信的不稳定性。蓝牙连接经常会断开,数据传输也可能出错。所以代码要处理各种异常情况,比如连接断开、数据丢失、超时等。

以前的代码,对异常处理很粗糙,很多地方根本没处理异常。重构的时候,我把异常处理都补上了,确保在各种异常情况下,应用都能正常运行,不会崩溃。

第三个挑战是数据的实时性。可穿戴设备的数据是实时产生的,应用要实时处理和展示。所以数据处理的链路要短,延迟要低。

在重构的时候,我优化了数据处理的流程,减少了中间环节,让数据能更快地从设备传到UI展示。

第四个挑战是AI算法的集成。AI可穿戴设备的核心是AI算法,算法的集成和调用也是一个挑战。算法的输入输出格式、调用时机、结果处理,都需要仔细设计。

我把AI算法的调用封装成了独立的模块,对外提供统一的接口。这样,算法的升级和替换,不会影响其他模块。

重构后的效果

重构完成之后,效果非常明显。

第一个效果是代码量减少了。重构前十几万行代码,重构后只有八万多行,减少了近三分之一。很多重复的代码被消除了,很多无用的代码被删掉了。

第二个效果是可读性提升了。统一的命名、清晰的分层、完善的注释,让代码的可读性大大提升。新人接手项目,以前要一周才能看懂,现在一两天就能上手。

第三个效果是bug减少了。重构的过程中,发现并修复了很多隐藏的bug。而且有了单元测试之后,新的bug也不容易引入了。上线后的故障率,比以前低了很多。

第四个效果是开发效率提升了。以前加一个新功能,要花大量时间理解旧代码,还要担心改出问题。现在代码结构清晰,加新功能很快,也更有信心。

第五个效果是性能提升了。重构过程中做的性能优化,让应用的运行更流畅,耗电也更少了。用户反馈,应用比以前好用多了。

给需要重构的朋友的建议

如果你也面临烂代码需要重构,我有几个建议。

第一,不要畏惧重构。很多人面对烂代码,觉得无从下手,就不敢动。但烂代码越放越烂,迟早要重构。早重构比晚重构好,越晚代价越大。

第二,先理解再动手。不要一上来就改代码,先花时间理解整个系统的结构和业务逻辑。理解清楚了,再动手,才能事半功倍。

第三,小步快跑。每次只改一小部分,改完就测试。不要追求一步到位,要循序渐进。

第四,保持功能不变。重构不是重写,不要在重构的同时改功能。先把结构理顺,再考虑功能的优化。

第五,要有测试兜底。如果没有测试,重构的风险很大。如果项目没有测试,可以在重构之前先补一些关键的测试,或者在重构的过程中逐步补上。

第六,争取团队的支持。重构是一个系统工程,需要团队的支持。要让团队成员理解重构的价值,一起参与进来,而不是一个人单打独斗。

写在最后

这次AI可穿戴项目的重构,花了我两周时间,但我觉得非常值得。

从最开始的无从下手,到最后的优雅代码,这个过程虽然辛苦,但很有成就感。重构不只是改善了代码质量,更重要的是,让我对这个项目有了深入的理解,也提升了自己的架构设计能力。

烂代码不可怕,可怕的是面对烂代码不敢动手。只要有正确的方法和足够的耐心,任何烂代码都能变成优雅的代码。

如果你也在维护一个烂代码项目,不要抱怨,行动起来,开始重构吧。当你看到代码一天天变得清晰优雅的时候,你会觉得一切努力都是值得的。

最后用一句话来结束这篇文章:"代码是写给人看的,只是顺便能在机器上运行。优雅的代码,是对自己和他人的尊重。"

愿每一个程序员,都能写出优雅的代码,也都有勇气重构烂代码。