当前位置: 首页 > 科技观察

关于代码质量下降的思考_0

时间:2023-03-15 13:07:43 科技观察

一个软件项目,从探索阶段到发展方向明确阶段,都会经历一个由简单到复杂的过程。需求的不断叠加,会让系统越来越大,功能越来越多,公司的业务越来越多。缩放还使软件系统的生命周期更长。在业务变得复杂的过程中,在各种原因的驱动下,代码质量会下降,维护和开发新功能的成本也会相应增加,推倒重开发的成本也很吓人。代码质量下降的步骤大多数情况下,编码设计的最高质量是按照第一个版本的要求进行编码,但只要需求发生变化,原有的编码设计就会被打乱,软件质量会越来越差。.或者没有设计。代码的变化趋势已经到了项目的中期。如果有新功能或者bug修复,老大会给我一天写处理代码吗?逾期会被骂;这个没用的功能,做了也没人用,随便写写,早点做完,早点做其他事情;我现在手头的工作那么多,你插一个新的功能,我只能乱来,而且团队中不同层级的人员写的代码更是不一样等等,这些都是我们在工作中会遇到的问题实际工作。责任感让我们想先这样写,后面再重构。一般来说,后来重构意味着永远不会重构。以上这些都会让我们添加不好的代码,混乱的业务逻辑分布在我们系统的各个地方,部门人事变动,新员工更不可能理解那些乱七八糟的东西,然后推送不好的代码,试图实现清零业务逻辑,很容易迷失在混乱的代码中。最直接的后果就是这些乱码会增加新功能的开发周期。领导问为什么现在开发一个功能这么慢?是不是人手不够,再招几个人吧。这个乱七八糟的项目不是新员工能搞定的。你会发现,虽然员工多了。但是开发效率还是上不去。随着项目的发展,让我们构建一个新系统来完全替代旧项目。我们可以使用最新的框架和更好的实现方法来完成这个系统。这种幼稚的想法会无数次的出现在团队成员的脑海中。旧系统的业务非常复杂。新系统在兼容老系统逻辑的同时,老系统也在更新需求,增加功能。旧系统将继续运行,直到新系统能够与旧系统完全竞争。如果你的新系统开发时间太长,等到完成时,员工可能不知道改了多少批次,代码又会变得一团糟,又开始循环。在软件退化越来越严重的过程中,我们也在思考和改变现有的系统,如何让系统有更长的生命周期,提高代码的质量,防止其退化,并有更好的可维护性和可扩展性?即根据需求的变化调整架构和代码,不断打破原有的设计,保持清晰,而不是让它烂在那里。对于渐进式架构,大多数人能想到的最直接的解决方案就是从架构入手,引入多维架构、微服务、领域驱动模型(DDD)等,从上层引入新的架构模型层次化设计,或者根据需求的变化不断调整代码的层次和模块,再加上理论知识的应用,会让业务代码的结构更加清晰。严格的分层可以让整体的业务边界更加清晰。前提是我们要从多个维度审视系统架构,思考如何对现有架构进行合理的改动。从不同的角度分析和改进现有架构。比如项目初期,业务比较简单,最简单的分层架构就可以实现项目需求。观察我们的架构可能是这样的,一个从上到下的松散分层架构:松散分层架构后来加入了缓存,加入了消息队列,业务的不断扩展又加入了不同的数据库nosql。随着v2.0和v3.0的业务升级,新服务必须兼容旧功能等,如果保持原有的层级结构,很快就会出现逻辑代码堆积的问题,业务层之间的引用混乱。文件中有几千行代码,当需求发生变化时,全身心地调动起来,体现出及时调整结构的必要性。一定要重用依赖倒置原则。层不应该依赖于实现,而是依赖于抽象。例如,我们的基础设施层应该为其他三层提供支持。基础设施层可以实现其他层定义的接口进行抽象。从这个角度来说,我们的基础设施层应该在最上面,也可以在左边,也可以在右边。基础设施应用依赖倒置之后,我们调用抽象接口,你会发现层的概念没有了,层的概念被打破了,我们可以更激进一些,把基础设施??层剥离出来,使用各种适配器来访问各种组件平整层与层之间的关系,调整结构为六方结构。不要用六边形架构来固化自己的思维。根据业务和系统的发展调整您的系统架构,使系统更具可扩展性和可维护性。调整非常老的项目的结构是痛苦的。在进行转型之前,必须得到管理层的全力支持。这种工作只能自上而下地推进,痛苦的过程最终会换来后期维护的快乐。在代码层面,除了团队中的代码规范,大家都要遵守,这样才能更加统一代码风格,使用lint工具检查代码。各种语言的lint工具可以在早期检测出你的代码中不合理的地方。还有以下方法。功能模块化最让程序员喜欢的是编码实现特定的功能。这才是我们真正发挥内功的地方。我们可以套用各种模式,把代码和逻辑写的漂亮,但是放在整个项目结构中,被调用的时候感觉太不符合使用过程了。根本原因是我们的模块划分不正确,模块之间的依赖耦合太强了。这通常是优雅地编写和粗暴地使用。依赖倒置的原则仍然适用于模块之间的划分。模块之间的依赖关系通过依赖注入被反转和解耦。模块对外暴露的接口尽可能少,它们之间的调用依赖于接口。抽象的好处是可以让你更清楚地定义模块的边界。物体之间是合作关系,不是纠缠关系。业务越复杂,需要操作的对象就越多。如果物体的边界不清晰,就会发生纠缠。要么一个对象负责太多的事情,要么几个对象同时做一件事,逻辑就乱了。当你发现对象不再是协作关系时,你应该停下来,从高处看你组织的代码,分解大对象,明确责任线,这就是单一功能原则。很多同学不知道如何判断一个对象的职责,或者一个属性是否属于一个对象。最简单的方法就是判断这个属性的变化是否会影响到一个对象,如果没有,则不属于这个对象。另外,面对新的业务需求,敢于打破原有的代码设计。不要过度开发,删除无用代码定期检查并删除无用代码。少写或者不写自己觉得以后可能用到的方法。这些多余的代码会成为以后重构的绊脚石,你会把精力浪费在这些不用的代码上,去寻找是否被使用。不得不提的SOLID原则,就是Bob大叔(RobertC.Martin)的SOLID编码原则,是设计模式的基石,必须不断地应用和实践。随着coding时间的增长,越来越觉得SOLID真的是一盏明灯。当你在黑暗中找不到路时,它会指引你回到正确的道路上。如果你对SOLID原则的应用比较熟练,以上提到的几项完全可以忽略。(1)单一职责原则(SingleResponsibilityPrinciple)每个对象只有一个职责,明确了对象的边界。文中提到的对象是合作关系。《不纠缠》中提到,如何判断一个属性是否属于某个对象。(2)开闭原则(OpenClosedPrinciple)可以扩展(extension),不能修改(modification)。该原理将代码中不变的逻辑抽取出来,将可变的代码封装起来。策略模式很好地体现了这一原则。模型。(3)里氏替换原则(LiskovSubstitutionPrinciple)继承必须保证超类拥有的属性在子类中仍然持有。LiskovSubstitutionPrinciple主要解释了关于继承的一些原则,即什么时候应该使用继承,什么时候不应该使用继承,以及背后的基本原理。里氏代换是继承重用的基础,它反映了基类与子类的关系,是对开闭原则的补充,是对实现抽象的具体步骤的规范。里氏代换原则最著名的例子是“正方形不是长方形”。(4)接口隔离原则(InterfaceSegregationPrinciple)尽量把臃肿庞大的接口拆分成更小更具体的接口,让接口只包含调用者感兴趣的方法,这就是我们将复杂的功能分成模块的原因应用法律。接口隔离原则和单一职责原则都是为了提高类的内聚性,降低类之间的耦合度,但是两者不同的是:单一职责原则侧重于职责,而接口隔离原则侧重于对接口的依赖隔离。单一职责原则主要是约束类,针对的是程序中的实现和细节;接口隔离原则主要是对接口进行约束,主要针对抽象的构建和程序的整体框架。(5)依赖倒置原则(DependenceInversionPrinciple)抽象不应该依赖于细节,细节应该依赖于抽象。换句话说,针对抽象(接口)进行编程,而不是针对实现细节。这个原则在上面讲改进架构的时候有提到。在重构代码和开发新功能的同时,需要重构之前的逻辑,坚持开闭原则,可以达到事半功倍的效果。工作之余浏览已有的代码逻辑。我们每天都在成长,我们对系统的认知也在不断变化,我们的思维方式也在不断变化。当我们用现在的眼光来看旧的代码逻辑时,大部分都能发现。可以优化的地方,或者隐藏错误的地方,重构它。不要以为这些只是挤牙膏的调整,任何事情都有一个从质变到量变的过程。代码审查(codereview)代码审查在团队中还是很有必要的。代码审查不是口水战,也不是批评会。如果只是走个形式,代码审查的意义就不存在了。您编写的代码需要被团队成员理解。以后新员工维护你写的功能。代码审查是团队其他成员快速了解新代码意图的一种方式。大部分团队的程序员水平参差不齐,对业务和系统的理解深度也不一样。让团队不同的人去codereview,及时发现代码中的不足,哪里逻辑有问题,哪里业务没有考虑周全。Codereview一次提交的代码太多的时候,不可能一下子看完,或者看不懂。需要先回顾整体思路,再回顾主要逻辑的实现,最后才是实现细节。需要说明的是,codereview并不能完全发现代码中隐藏的bug,所以不要把找bug的任务和它混为一谈。学习再多的架构或框架知识也无法阻止我们编写糟糕的代码。但是当你静下心来打磨产品或者认真实现一个功能的时候,你就会在乎自己写的代码,主动去写更清晰的逻辑,改变和想办法处理不好的代码。希望这篇文章能对你有所帮助。