gpt4 book ai didi

c# - 依赖注入(inject)进一步深入 "chain"

转载 作者:行者123 更新时间:2023-12-01 07:10:12 24 4
gpt4 key购买 nike

我一直在阅读如何编写可测试代码,并偶然发现了依赖注入(inject)设计模式。

这种设计模式非常容易理解,而且实际上没有什么意义,对象请求值而不是自己创建它们。

但是,现在我正在考虑如何将其用于我当前正在开发的应用程序,我意识到它存在一些复杂性。想象一下下面的例子:

public class A{

public string getValue(){
return "abc";
}
}


public class B{
private A a;

public B(A a){
this.a=a;
}
public void someMethod(){
String str = a.getValue();
}
}

单元测试 someMethod () 现在会很容易,因为我可以创建 A 的模拟并让 getValue() 返回我想要的任何内容。

类 B 对 A 的依赖是通过构造函数注入(inject)的,但这意味着 A 必须在类 B 之外实例化,因此此依赖项已移至另一个类。这将重复很多层,并且在某些点上必须完成实例化。

现在的问题是,使用依赖注入(inject)时,您是否会不断通过所有这些层传递依赖项?这是否会降低代码的可读性并增加调试时间?当您到达“顶层”时,您将如何对该类进行单元测试?

最佳答案

我希望我正确理解你的问题。

注入(inject)依赖项

不,我们不会将依赖关系传递到所有层。我们只将它们传递给直接与它们对话的层。例如:

public class PaymentHandler {

private customerRepository;

public PaymentHandler(CustomerRepository customerRepository) {
this.customerRepository = customerRepository;
}

public void handlePayment(CustomerId customerId, Money amount) {
Customer customer = customerRepository.findById(customerId);
customer.charge(amount);
}
}

public interface CustomerRepository {
public Customer findById(CustomerId customerId);
}

public class DefaultCustomerRepository implements CustomerRepository {

private Database database;

public CustomerRepository(Database database) {
this.database = database;
}

public Customer findById(CustomerId customerId) {
Result result = database.executeQuery(...);
// do some logic here
return customer;
}
}

public interface Database {
public Result executeQuery(Query query);
}

PaymentHandler 不了解数据库,它只与CustomerRepository 通信。 数据库的注入(inject)在存储库层停止。

代码的可读性

在没有框架或库帮助的情况下进行手动注入(inject)时,我们最终可能会得到包含许多样板代码的工厂类,例如return new D(new C(new B(), new A()); 在某些时候可能可读性较差。为了解决这个问题,我们倾向于使用像 Guice 这样的 DI 框架来避免编写这么多工厂。

但是,对于实际执行工作/业务逻辑的类,它们应该更具可读性和可理解性,因为它们只与直接协作者交谈并完成他们需要做的工作。

单元测试

我假设“顶层”指的是 PaymentHandler 类。在此示例中,我们可以创建一个 stub CustomerRepository 类,并让它返回一个我们可以检查的 Customer 对象,然后将该 stub 传递给 PaymentHandler 检查是否收取了正确的金额。

总体思路是传入假协作者来控制他们的输出,以便我们可以安全地断言被测类(在本例中为 PaymentHandler 类)的行为。

为什么要使用界面

正如上面的评论中提到的,最好依赖接口(interface)而不是具体的类,它们提供更好的可测试性(易于模拟/ stub )和更容易的调试。

希望这有帮助。

关于c# - 依赖注入(inject)进一步深入 "chain",我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/15879464/

24 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com