是否需要依赖倒转来保证调用者和被调用者之间的解耦?

问题描述 投票:0回答:1

我试图通过本教程中的一些简单但具体的代码和类(在Python中实现)来理解依赖倒置原理(DIP)。我总结一下(用我自己的评论和理解),以减轻您经历整个事情的痛苦。

基本上,我们正在构建一个货币转换器应用程序,其中我们将main应用程序逻辑与货币转换器本身分开。代码(我的一些注释和文档字符串)如下。

片段1
#!/usr/bin/env python3
# encoding: utf-8

"""Currency converter application using some exchange API."""
class FXConverter:
    """The converter class."""
    def convert(self, from_currency, to_currency, amount):
        """
        Core method of the class. Assume the magic number 1.2 is from some API like 
        Oanda
        """
        print(f'{amount} {from_currency} = {amount * 1.2} {to_currency}')
        return amount * 1.2


class App:
    """The Application"""
    def start(self):
        """The main method to create and invoke the converter object."""
        converter = FXConverter()
        converter.convert('EUR', 'USD', 100)


if __name__ == '__main__':
    app = App()
    app.start()

现在,教程声称(直接引用)

将来,如果FX的API发生变化,就会破坏代码。另外,如果您想使用不同的 API,则需要更改 App 类。

所以他们提出了这个。

片段2
#!/usr/bin/env python3
# encoding: utf-8

"""Currency converter application using dependency inversion."""
from abc import ABC


class CurrencyConverter(ABC):
    def convert(self, from_currency, to_currency, amount) -> float:
        pass

class FXConverter(CurrencyConverter):
    def convert(self, from_currency, to_currency, amount) -> float:
        print('Converting currency using FX API')
        print(f'{amount} {from_currency} = {amount * 1.2} {to_currency}')
        return amount * 1.2 # The tutorial seems to have a typo here. 

class App:
    def __init__(self, converter: CurrencyConverter):
        self.converter = converter

    def start(self):
        self.converter.convert('EUR', 'USD', 100)

if __name__ == '__main__':
    converter = FXConverter()
    app = App(converter)
    app.start()

问题

对我来说,这句话似乎并不真实,这正是我无法理解 DIP 的核心原因。即使

FXConverter
使用不同的交换 API(假设 Bloomberg 而不是 Oanda),更改不会保持本地化到
convert
方法吗?只要
convert
方法保持签名

convert(str, str, float)->float # The strings must be valid currency names 

App.start
应该很高兴。维护这个有效方法签名的必要性是

  • 即使在 DIP 版本中也没有取消。
  • 以类型更安全的语言(如 Rust 或 C++)自动强制执行。在更严格的语言中,我可能会枚举可能的货币范围,以确保字符串变量不是自由形式,如 US$£ 等。

这就是为什么我根本看不到 DIP 如何有助于更好的解耦,而我们真正需要的是遵守静态类型语言中的函数/方法签名?

一般来说,当

A
调用
B
(对象方法或函数等)时,我们可以假设

  • A
    不了解
    B
  • 的内部运作
  • B
    不知道
    A
    对结果做了什么

以便自动执行所需的解耦?

python oop solid-principles object-oriented-analysis dependency-inversion
1个回答
0
投票

这个解释实际上听起来有点令人困惑。

如果您的

FXConverter
实现发生变化
App
也没关系,即使没有 DI。

如果

FXConverter
的 API 发生变化,
App
会中断,无论有或没有 DI。

但是 DI 使您可以选择将

FXConverter
替换为其他类别,例如改进的
GXConverter
而不触及
App
。 这就是 DI 的意义所在。

您想要交换实现的一个典型示例是测试,其中您用模拟替换类(使用术语松散),这可能提供预设结果、记录和/或检查调用或使用简化的算法。

© www.soinside.com 2019 - 2024. All rights reserved.