Skip to content
快速预览

表达原则

✍️ w 🕒 2023-07-23 12:23:51(10 months ago) 🔗 G.设计模式

可读性差的代码难以理解,这不仅会造成诸多误解和麻烦,还会导致项目交付效率变低,代码的可读性差,没能很好地串联起代码内在的逻辑,在维护代码时候或多或少会遇到

  • 接手维护项目,却发现文档缺失、代码无注释,加上维护人离职,基本只能靠猜来梳理代码逻辑。

  • 代码风格过于抽象(命名过短、魔鬼数字、重名方法等),看不懂,也不敢轻易修改。

  • 运行代码出现故障时,不打日志,不抛异常,导致定位问题需要耗费很长时间。

  • 大段的if-else代码嵌套组合,调用逻辑复杂冗长,扩展性差,重构优化费时、费力。

为了提高代码的可读性,就需要表达原则

提升代码可读性代码特点

为什么要提高代码可读性,通过四个方面可以理解

  1. 易于维护,设计文档、需求文档和口头交流只能表达部分业务逻辑的意图。可读性高的代码,能让阅读者在阅读时快速理解编写者的意图
  2. 易于重构,代码的可读性太差在某种程度上决定了你重构意愿的大小
  3. 易于测试,可读性高的代码,参数与输出都更清晰,在测试时能更精准地找到对应逻辑和问题点
  4. 易于应用设计模式,好读懂代码跟方便理解分析出要使用较好的设计模式进行重构

表达原则

虽说编写文档能够表达软件开发意图,但事实上,你可能很讨厌写文档,这是因为大部分文档都与代码没有直接关系,并且随着代码的不断调试与修改,文档会变得越来越难以与最新的真实情况同步。

另外,你可能也没有太多时间阅读文档,需求上线、Bug 修复、多项目并发是现在程序员的日常现状。因为时间紧、任务重,你可能只能边改代码边学习,这时一份逻辑清晰的代码才是你真正需要的。

这些情况下可以使用,表达原则(Program Intently and Expressively,简称 PIE),起源于敏捷编程,是指编程时应该有清晰的编程意图,并通过代码明确地表达出来,代码即文档,在开发代码时,应该更注重代码表达的意图是否清晰

  • 代码表现形式:在命名(变量名、方法名、类名)、代码格式、注释等方面的改进,无论是变量名、类名还是方法名,好的名字能快速准确地传达要表达的含义,而缩写、自定义名称会让代码变得难以理解,命名的优化加上注释的说明让源代码的逻辑变得清晰起,以下面代码为例需要去整阅读后也之态知道代码在做什么事
java
public class T {

    private Set<String> pns = new HashSet();

    private int s = 0;

    private Boolean f(String n) {return pns.contains(n);}

    int getS() {return s;}

    int s(List<T> ts, String n) {

        for (T t :ts) 

            if (t.f(n)) 

                return t.getS();

        return 0;

    }

}

在命名的优化加上注释的说明改造后代码变得清晰起来

java
/**

 * 获取球队比赛得分

 **/

public class Team {

    private Set<String> playerNames = new HashSet(); //保证名字不重复

    private int score = 0; //默认为零

    

    /**

     * 判断是否包含球员

     * @param playerName

     * @return

     */

    private Boolean containsPlayer(String playerName) {

        return playerNames.contains(playerName);

    }

    

    /**

     * 知道队伍,直接获取分数

     * @return

     */

    public int getScore() {

        return score;

    }

    

    /**

     * 通过队员名字查找所属队伍分数

     * @param teams 支持多个队伍

     * @param playerName 

     * @return 兜底为0分,不出现负分

     */

    public int getTeamScoreForPlayer(List<Team> teams, String playerName) {

        for (Team team :teams) {

            if (team.containsPlayer(playerName)) {

                return team.getScore();

            }

        }

        return 0;

    }

}
  • 控制流和逻辑:尽量分离控制流和逻辑,让代码变得更容易理解,如果过多if嵌套无法保证逻辑简单清晰
java
public List<User> getUsers(int id) {

    List<User> result = new ArrayList<>();

    User user = getUserById(id);

    if (null != user) {

        Manager manager = user.getManager();

        if (null != manager) {

            List<User> users = manager.getUsers();

            if (null != users && users.size() > 0) {

                for (User user1 : users) {

                    if (user1.getAge() >= 35 && "MALE".equals(user1.getSex())) {

                        result.add(user1);

                    }

                }

            } else {

                System.out.println("获取员工列表失败");

            }

        } else {

            System.out.println("获取领导信息失败");

        }

    } else {

        System.out.println("获取员工信息失败");

    }

    return result;

}

代码嵌套了大量的 if else随着判断条件逐渐增多,嵌套就会增多。代码逻辑越多,你就越容易搞不清楚逻辑是什么,因为看到最内层的代码时,你已经忘记前面每一层的条件判断是什么了。

重新优化改变控制流,先判断会出现失败的条件,一旦出现优先退出

java
public List<User> getStudents(int uid) {

    List<User> result = new ArrayList<>();

    User user = getUserByUid(uid);

    if (null == user) {

        System.out.println("获取员工信息失败");

        return result;

    }

    Manager manager = user.getManager();

    if (null == manager) {

        System.out.println("获取领导信息失败");

        return result;

    }

    List<User> users = manager.getUsers();

    if (null == users || users.size() == 0) {

        System.out.println("获取员工列表失败");

        return result;

    }

    for (User user1 : users) {

        if (user1.getAge() > 35 && "MALE".equals(user1.getSex())) {

            result.add(user1);

        }

    }

    return result;

}
  • 惯性思维:找出常犯的一些惯性思考方式并逐一改进,要避免一次性代码一次性代码一旦修改需要,多处就得跟着修改,而多次修改又可能会出现遗漏的风险,要避免复制粘贴代码复制代码往往都对内部逻辑不了解,等真正出现问题时候再去修改发现梳理逻辑更加困难, 避免写超长代码避免过度简化命名和表达式避免写是什么的注释,代码的命名和结构如果能直接反映出来“是什么”的话,我们就不应该用注释去表达,因为看代码一眼就能明白,应该多写“为什么”的注释,比如,为什么要多加一个适配的方法,原因可能是线上 xxx 问题引起,或临时修复的Bug,后续可能随 xxx 接口调整而废弃,“为什么”的注释还有一个好处:尤其在早期快速迭代过程中,能给后来的维护者提供一个优化的切入点,而不至于交接代码后让维护代码的人看不懂、不敢动

表达原则的核心思想在于:通过代码清晰地表达我们的真实意图,虽然软件开发过程中会有诸多文档,比如,架构设计文档、流程文档、PRD 文档等,但这些文档并不足以帮助我们正确理解代码是如何运行和组织的,很多时候我们只能通过阅读代码来掌握软件的真实运行情况。

我们之所以应该把提高代码可读性作为第一要务,就是因为读代码的次数远比写代码的次数多

总结

表达原则是指代码应该易于阅读、易于理解、易于维护、易于重构、易于测试和易于应用设计模式。这些特点可以提高代码的可读性,使得代码更易于被理解和修改。

Released under the MIT License.