耦合是指代码库中不同组件或模块之间的依赖程度。高耦合可能会导致难以理解,修改和维护的代码。
在本文中,我们将探讨各种策略,以减少耦合和促进清洁代码,但首先:
如何测量它?
没有确定的指标可以测量耦合,这是您可以采用的一种方法。
依赖关系分析:分析代码库中类,模块或软件包之间的依赖关系。静态代码分析仪或依赖性可视化工具等工具可以帮助识别不同组件之间的关系和依赖关系。高水平的互连和依赖性表示耦合的程度更高。
工具:
-
jdepend
-
结构101
-
Sonarqube(除了静态代码分析外,还提供了一个称为“依赖关系检查”的模块,可视化模块,软件包和类之间的依赖项。)
-
maven依赖关系插件:通过运行
dependency:tree
目标,您可以获得一个类似树的结构,以说明项目模块和库的依赖关系层次结构。
解决方案
-
告诉,不要问(TDA)原理
-
避免方法呼叫链
-
利用事件
-
偏爱继承的接口
-
偏爱继承
-
用于参数化应用程序的外部配置
告诉,不要问(TDA)原理
减少耦合的一种有效方法是遵循“告诉,不要问”原理。与其暴露对象的内部状态供他人推理,不如将对象本身内的行为封装。通过限制对对象状态的外部访问,我们可以减少依赖关系并使代码库更可维护。
int age = person.getAge();
if (age >= 18) {
// some java code
}
更好的方法
if (person.isAdult()) {
// some java code
}
您不会总是能够应用此规则,而是至少两次,然后将数据从对象提取到外部世界。
避免方法呼叫链
链接方法调用可能会导致对象之间的紧密耦合,从而使代码更脆,更难修改。
Energy.getInstance().getEnergyDropManager().getDrops();
Energy
与EnergyDropManager
有直接链接是很好的,但是请考虑谁在打电话及其所需的一切。如果需要getDrops()
,则需要99%的电话,您应该重新考虑此方法的目的以及将其移至Energy
是否更明智。
Energy.getInstance().getDrops();
另外,考虑将功能构成管道或将代码作为一系列嵌套转换。这种方法促进了更模块化和脱钩的设计。
public class FunctionChainingExample {
static Logger logger = Logger.getLogger(FunctionChainingExample.class.getName());
private static Function<Integer, Integer> multiply = x -> x * 2;
private static Function<Integer, Integer> add = x -> x + 2;
private static Function<Integer, Unit> logOutput = x -> {
logger.info("Data:" + x);
return Unit.unit();
};
public static Unit execute(Integer input) {
Function<Integer, Unit> pipeline = multiply
.andThen(add)
.andThen(logOutput);
return pipeline.apply(input);
}
public static void main(String[] args) {
execute(10);
}
}
利用事件
响应事件并相应调整其行为的应用程序在现实世界中可以更灵活和适应性。
选项
-
有限状态机,
-
观察者模式, p> li>
-
发布/订阅,
-
反应性编程,
-
流
偏爱界面和组成而不是继承
继承可以在类之间引入强耦合,从而导致很难扩展和修改的代码。取而代之的是,偏爱界面而不是继承。接口允许多态性而无需与继承相关的紧密耦合。
public interface Renderer {
void render();
}
public class CircleRenderer implements Renderer {
public void render() {
// Render a circle
// ...
}
}
public class SquareRenderer implements Renderer {
public void render() {
// Render a square
// ...
}
}
public class RendererApp {
public static void main(String[] args) {
Renderer circleRenderer = new CircleRenderer();
circleRenderer.render();
Renderer squareRenderer = new SquareRenderer();
squareRenderer.render();
}
}
优先组成而不是继承
应该设计的类是由其他类或模块组成的,而不是严重依赖继承关系。
public interface Engine {
void start();
}
public class GasEngine implements Engine {
public void start() {
// Start the gas engine
// ...
}
}
public class Car {
private Engine engine;
public Car(Engine engine) {
this.engine = engine;
}
public void startEngine() {
engine.start();
}
}
用于参数化应用程序的外部配置
要减少耦合并提高灵活性,请考虑使用外部配置参数化应用程序。这可以通过静态配置文件或API后面的服务来实现。
通过外部化配置,您可以在不修改代码本身的情况下修改应用程序的行为,从而减少依赖关系并改善代码库的适应性。
结论
减少耦合对于维护干净可维护的代码库至关重要。通过遵循诸如“告诉,不要问”原则之类的策略,避免方法呼叫链,利用事件,偏爱接口而不是继承以及外部配置,您可以有效地减少耦合并实现更模块化和灵活的代码库。接受这些实践不仅可以提高代码可维护性,而且还可以提高软件项目的可扩展性和可扩展性。