体面编码之通用原则


更喜欢函数性方法。相比副作用,不可变的状态使代码不易出错,并且更容易推理。

最小化持有状态。任何形式的状态(例如变量,缓存)往往是复杂性和问题的根源,因此最好尽可能少地保留它。如果约束允许,更喜欢在需要时导出信息,以便存储信息。

帮助编译器/转发器和静态分析工具为您提供帮助。这些工具可以在代码运行之前检测代码中的问题,从而缩短反馈循环。请注意您的工具可以检测到的问题,并编写代码来帮助他们。例如,使用注释,例如@Override,使用常量变量,避免不必要地初始化变量,避免破坏类型安全系统,并避免抑制警告。

在抑制静态分析警告或完全禁用导致它的规则之前,请仔细考虑。考虑为什么首先启用和配置规则的原因。规则文档页面通常描述规则的动机。您可能会违反最佳实践(或项目实践),或使用容易出错或弃用的技术。进一步阅读:切斯特顿的围栏

对象和类
赞成不变性。不可变对象通常比可变对象更简单且使用更不容易出错。在多线程上下文中尤其如此。

防止构造无效对象。无效的对象通常会迟早出现问题。最好通过让构造函数/工厂验证它们来尽早失败。

避免绕过部分初始化/填充的对象。这样做会使创建过程变得困难,并且在初始化完成之前就有可能使用它们。

避免使用多用途数据类。这些通常是数据或DTO(数据传输对象)类,当需要表示的多个事物除了少数字段之外非常相似时,以不同方式部分填充并用于不同目的。它们模糊了实际域项的外观,容易出错,并且难以重构。

数据和值
创建和使用属于领域建模的数据类型。避免直接使用字符串做字段,只是因为它可能并且看起来很方便。基于领域的数据类型是面向对象编程的关键,为许多方法提供自然的家园,并为编译器提供可用于检测错误使用的信息。

在领域数据类型中包括度量单位/幅度。这使领域模型与编译器一起使用以防止无效计算。这类似于使用导出的物理方程的输入和输出单元的维度分析来验证它是否正确导出。它还消除了在属性/变量名称中包含单位(例如MWh)的需要。

通常,为魔术数字提取常量。然而,在某些情况下这样做会增加噪音,例如零。

方法
避免做调用者不合理期望的事情。方法名称传达了期望 - 避免令人惊讶的副作用。

因失败的先决条件而提前返回。避免将大多数/所有方法放在if语句(或许多嵌套语句)中的需要使其更容易阅读。

避免使用长参数列表。他们很容易让调用者以错误的顺序传递参数,即使有IDE的帮助。在非类型语言中或者参数类型相同时尤其如此。请改用参数对象或构建器。

直观地排序参数。把更重要的参数放在第一个附近。把相关的那些放在一起。帮助选择直观顺序的一个技巧是构造一个描述方法调用的句子; 参数通常自然地落入句子中的顺序。

参数顺序一致。在存在重载或许多方法采用类似参数的情况下,所有方法都应首先采用公共参数。

避免布尔参数。在读取调用代码时,布尔参数使得很难知道调用的意图。考虑每个案例的双元素枚举,参数对象或单独的方法。进一步阅读:布里陷阱的陷阱,由Ariya Hidayat撰写

逻辑
基于标识符的实现逻辑,而不是基于名称。名称通常不保证是唯一的,并且易于改变。使用标识符识别事物来驱动逻辑。

通过否定表达来避免逆转条件。处理fals块中的case使得构造更容易遵循,尤其是在存在多个else if的情况下。