龙空技术网

谈谈我对代码质量的理解

会稽奇怪的银鱼 60

前言:

如今大家对“好的代码是什么”可能比较看重,小伙伴们都想要了解一些“好的代码是什么”的相关内容。那么小编也在网络上收集了一些关于“好的代码是什么””的相关内容,希望大家能喜欢,你们快快来学习一下吧!

背景

作为一名计算机专业出身的学生,到如今在互联网大厂工作,我深刻认识到代码质量的重要性。在学生时代,我做项目更多是个人兴趣驱动,追求将项目跑通并实现功能给予的成就感,对项目质量几乎没有过多关注,只要能跑就行。然而,一旦进入工作,从个人solo过渡到多人协同开发,从0-1搭建项目变成了更多对已有代码的缝补扩展,高质量的代码,不仅意味着更高的协同效率,还意味着更低的故障风险。

代码坏味道

得益于计算机强大的编译能力,只要代码没有bug,那么计算机一定能帮助我们编译执行,得到预期的结果。而我们写的代码不仅是给计算机运行的,更多的是写给自己和协作者看的,试想一下面对着满屏随意的命名,冗长的方法,臃肿的类,以及各种魔法字符串,想必经验丰富的程序员也得捏一把汗。低质量的代码,不仅给维护带来了极高的成本,还给埋下了更多上线后故障的隐患。因此,写出能够让人轻易理解,维护,扩展的代码,才是一个软件开发工程师需要具备的基本硬实力。

在讨论什么是好代码之前,我们先讨论一下常见的代码坏味道。

代码换味道

2.1 冗余代码(Duplicated Code)

方法过长,包含大量的逻辑操作,难以理解和维护。

public void calculateArea(int length, int breadth) {    int area = length * breadth;    System.out.println("Area: " + area);}public void calculatePerimeter(int length, int breadth) {    int perimeter = 2 * (length + breadth);    System.out.println("Perimeter: " + perimeter);}
2.2 过长方法(Long Method)

方法包含了太多的步骤以及过于复杂的逻辑。

public void processOrder(Order order) {    // 一个方法包含了太多的步骤以及过于复杂的逻辑    // ...    // ...    // ...}
2.3 过长参数列表(Long Parameter List)

方法的参数过多,影响代码的可读性和易用性,加大了传参错误的风险。

public void createUser(String username, String password, String email, String phoneNumber, String address) {    // 方法体}
2.4 过长类(Long Class)

一个类包含过多的属性和方法,违反了单一职责原则。

public class Customer {    private String name;    private String address;    private String contactNumber;    // ... 更多的属性 ...    public Customer(String name, String address, String contactNumber) {        this.name = name;        this.address = address;        this.contactNumber = contactNumber;        // ... 初始化其他属性 ...    }    public void placeOrder(Order order) {        // 下订单逻辑    }    public void cancelOrder(Order order) {        // 取消订单逻辑    }    public void processPayment(Payment payment) {        // 处理付款逻辑    }    public void calculateDiscount() {        // 计算折扣逻辑    }    public void generateInvoice(Invoice invoice) {        // 生成发票逻辑    }    // ... 更多的方法和属性 ...}
2.5 命名不当(Poor Naming)

使用不具有描述性或误导性的变量、方法或类命名

public class Calculator {    public double calculateArea(int shapeType) {        if (shapeType == 1) {            return 3.14159 * 5 * 5; // 魔法数值,硬编码的圆的半径和圆周率        } else if (shapeType == 2) {            return 3.14159 * 10 * 10; // 魔法数值,硬编码的圆的半径和圆周率        } else {            throw new IllegalArgumentException("Invalid shape type"); // 魔法字符串,硬编码的错误消息        }    }    public String getMonthName(int month) {        if (month == 1) {            return "January"; // 魔法字符串,硬编码的月份名称        } else if (month == 2) {            return "February"; // 魔法字符串,硬编码的月份名称        } else {            throw new IllegalArgumentException("Invalid month"); // 魔法字符串,硬编码的错误消息        }    }}
2.6 魔法值(Magic Value)

在代码中直接使用未解释或不明确的硬编码值,降低了代码的可读性和可维护性。

public class Calculator {    public double calculateArea(int shapeType) {        if (shapeType == 1) {            return 3.14159 * 5 * 5; // 魔法数值,硬编码的圆的半径和圆周率        } else if (shapeType == 2) {            return 3.14159 * 10 * 10; // 魔法数值,硬编码的圆的半径和圆周率        } else {            throw new IllegalArgumentException("Invalid shape type"); // 魔法字符串,硬编码的错误消息        }    }    public String getMonthName(int month) {        if (month == 1) {            return "January"; // 魔法字符串,硬编码的月份名称        } else if (month == 2) {            return "February"; // 魔法字符串,硬编码的月份名称        } else {            throw new IllegalArgumentException("Invalid month"); // 魔法字符串,硬编码的错误消息        }    }}
2.7 过于复杂的条件表达式(Complex Conditional Expressions)

使用嵌套的条件语句和复杂的逻辑运算符,影响代码可读性和维护性。

if (a == 1 && b != 2 || c > 3 && d <= 4 || e == 5 && f >= 6) {    // Do something}
什么是好代码

什么是好代码

在我看来,优秀代码应该兼顾可读性,严谨性,扩展性以及可测性四个方面。

可读性

代码可读性是指代码的清晰度和易读性,即代码的易于被其他人理解和阅读。可读性是一种关注代码可维护性和可理解性的重要因素。

具有良好可读性的代码具有以下特点:

清晰的命名:使用有意义、描述性的变量、函数和类名,能够准确地传达其用途和功能。避免使用缩写或无意义的名称。适当的注释:在关键部分添加注释,解释代码的意图、算法、特殊考虑事项等。注释应该简洁明了,提供足够的上下文信息,而不是过多冗长或重复代码本身。良好的代码结构与缩进:通过正确的缩进和适当的代码布局,使代码块、条件语句和循环结构更易于阅读和理解。合理的代码结构能够帮助读者迅速定位和理解代码的逻辑。避免过长函数或方法:将复杂的代码拆分为更小且功能单一的函数或方法。这样做可以提高代码的模块化程度,并使每个函数/方法只关注一个特定任务,方便阅读和修改。一致的代码风格:保持一致的代码风格和约定,如缩进、括号的使用、命名规范等。这样做可以减少开发人员在阅读代码时的认知负荷,并加强整体代码的统一性。避免过多的复杂性:尽量避免过度复杂的逻辑,过多的嵌套和条件语句。简化代码可以提高可读性,并使代码更易于理解和修改。

代码可读性对于个人和团队的开发效率非常重要。可读性良好的代码不仅能够帮助其他开发人员快速理解代码的功能和实现方式,还能降低代码维护和调试的难度。同时,可读性好的代码也有助于促进团队合作和知识共享,提高项目的整体质量和稳定性。

严谨性

代码严谨性是指代码的正确性和健壮性,在各种情况下都能正常运行并处理异常情况。虽然我们在上线之前都会经历测试保障,但是测试永远是有限的,我们通常只会找一些关键测试用例进行覆盖。在线上正式运行时,面对复杂的接口入参,怎么处理好代码的严谨性是防范重大故障的有效措施。

错误处理:严谨的代码会主动检测和处理可能出现的错误情况。通过使用适当的错误处理机制,例如异常处理,可以捕获和处理运行时错误,提供适当的反馈和恢复策略,从而保证程序的稳定性。边界条件处理:严谨的代码会考虑到各种边界情况和可能的异常输入数据。它会验证输入数据的有效性和合理性,以防止潜在的问题和安全漏洞。边界条件包括极端值、空值、越界访问等。数据校验:严谨的代码会进行数据校验,确保数据符合预期的格式、类型和约束。例如,对输入数据进行验证以防止SQL注入攻击、文件上传时检查文件类型等。这样可以防止无效或恶意数据导致的问题。资源管理:严谨的代码会正确管理和释放系统资源,如数据库连接、文件句柄、内存等。它会确保及时释放资源,以避免资源泄漏和系统性能下降。安全性:严谨的代码会考虑到安全性问题,防止潜在的攻击和漏洞。例如,避免使用已知的不安全函数或方法、进行输入验证和过滤、使用加密机制等。弱依赖方式调用下游:使用try-catch方式调用下游接口,防止因为下游代码缺陷引起的连锁问题。扩展性

代码扩展性指的是代码的能力,可以轻松地进行功能的添加、修改和扩展,以适应未来需求的变化。这使得在未来应对类似需求的时候能够快速实现,显著提高效率。

模块化:扩展性强的代码会将不同的功能划分为独立的模块或组件。这样做可以降低模块之间的耦合度,使得新增功能的开发和现有功能的修改更加容易。模块化的代码还可以提高代码的可读性和可维护性。接口设计:扩展性强的代码会定义清晰和灵活的接口。通过良好的接口设计,可以降低模块之间的依赖性,使得新增功能的实现可以在不影响其他部分的情况下进行。接口的设计应该考虑到未来可能的变化和扩展需求,以支持灵活的功能增加和修改。依赖管理:扩展性强的代码会对外部依赖进行良好管理。它会尽量减少对特定库或框架的直接依赖,通过使用抽象层和接口来隔离具体实现。这样可以方便地切换或替换外部依赖,以适应未来的技术变化和需求变更。设计模式:使用适当的设计模式有助于提高代码的扩展性。例如,工厂模式、策略模式和观察者模式等可以在不修改现有代码的情况下添加新的功能或行为。设计模式提供了一种结构化的方式来组织和扩展代码。可配置性:扩展性强的代码会提供灵活的配置选项。通过将可变的参数或设置抽取到配置文件或数据库中,可以避免硬编码,使得功能的开启、关闭或修改可以在运行时进行,而不需要重新编译或修改源代码。可测性

代码可测性指的是代码的易于测试程度。具有良好可测性的代码能够方便地编写和执行各种类型的测试,包括单元测试、集成测试和系统测试。通过测试,可以验证代码的正确性、稳定性和性能,并及早发现和解决潜在的问题。

模块化:可测性强的代码会将不同功能划分为独立的模块或组件。这样做可以使得模块之间的依赖较少,测试单个模块变得更容易。模块化的代码还能够提高代码的可读性和可维护性。低耦合度:可测性强的代码会尽量降低模块之间的耦合度。通过减少模块之间的依赖,可以更容易对模块进行隔离测试。使用接口和抽象层等技术,可以实现松散耦合的设计,使得模块的测试更加独立和可靠。如何提升代码质量可读性

代码可读性对每个软件开发工程师来说都是最基本的要求,它在团队协作中扮演着重要的角色。为了提高代码可读性,以下是一些建议:

学习基础知识:《重构——改善代码的既有设计》是一本非常不错的教程,通过学习其中的内容,可以掌握常见的代码坏味道,并学会避免它们。同时,熟悉常见的重构方法,并能够灵活应用它们。遵循开发规范:团队内部制定的开发规范是非常重要的,遵循这些规范可以保持代码的统一性和一致性。这包括变量命名、代码缩进、函数和类的组织等方面的规范。积极参与代码评审:参与日常开发的代码评审,并从中学习和总结经验。通过与他人的代码交流和讨论,可以了解不同的编码风格和技巧,进一步提高自己的代码可读性。简洁清晰的表达:使用有意义的变量名和函数名,使代码更容易理解其功能和作用。在注释中解释复杂的逻辑或算法,确保其他开发人员能够快速理解代码的意图。适度拆分函数和模块:避免过长的函数,将其拆分为更小的函数,每个函数只负责完成一个特定的任务。这样可以提高代码的可读性和可维护性,避免代码变得混乱难懂。格式化和缩进:保持一致的代码格式,使用适当的缩进和空格,使代码结构清晰可见。合适的缩进可以帮助他人理解代码的层次结构。避免冗余和复杂的逻辑:删除重复的代码片段,并简化复杂的逻辑。简洁的代码更易于阅读和理解。注重命名规范:使用清晰、准确且有意义的变量和函数命名,避免使用无意义的名称或者过于缩写的方式。命名应该反映出变量或函数的用途和含义。

重构 改善代码既有设计

严谨性验证和异常处理:在编写代码时,确保对输入数据进行验证,包括类型、范围、长度等方面。同时,合理地处理可能出现的异常情况,例如使用try-catch语句捕获异常并进行适当的处理。推演和遗漏检查:在设计代码方案时,进行反复推演和思考,确保没有遗漏任何关键步骤或条件。通过仔细思考和测试各种可能的情况,可以大大减少潜在错误的风险。代码评审和总结:利用代码评审的机会,仔细检查他人代码中的严谨性问题,并从中学习。同时,在自己的代码评审过程中,重点关注严谨性问题,并将不好的地方进行总结和改进。单元测试:编写有效的单元测试可以帮助发现代码中的问题,尤其是一些边界情况和特殊情况。积极编写并执行单元测试,可以更好地保证代码的严谨性。扩展性对业务有深入理解:了解业务需求和发展趋势,可以更好地预测未来可能的变化和扩展方向。持续学习和积累业务知识,并与相关人员进行沟通和协作,有助于提高代码的扩展性。理解设计原则和模式:深入了解常见的设计原则和设计模式,如单一职责原则、开闭原则、依赖倒置原则等,可以指导代码的结构和组织方式,使其更易于扩展和修改。《设计模式之禅》就是一本很好的学习书籍。合理抽象和解耦:通过合理的抽象和模块化设计,将代码分解为独立的组件和功能模块,减少它们之间的依赖关系,从而提高代码的灵活性和可扩展性。避免过度设计:尽量避免在没有明确需求的情况下进行过度设计。过度设计可能会增加代码复杂性和维护成本,反而降低代码的扩展性。根据实际需求,采取适度的设计和抽象即可。

设计模式之禅

标签: #好的代码是什么 #代码什么样子是正常的 #好的代码是什么意思啊