Context

据我所知,SOLID OOP的依赖反转和接口隔离原则告诉我们根据interface编写程序,而不是内部细节.因此,我试图用Python开发一个简单的股票市场数据收集器,大致使用下面的对象图,其中main封装了应用程序业务逻辑、用户输入处理等.

  • 粉红色代表具体的函数或类,绿色代表抽象类
  • 空心箭头表示/实现关系的子类,实心箭头表示using关系(遵循Robert Martin的Clean Architecture约定)

Object diagram of stock price reader

因此,Main函数使用抽象接口,该接口根据符号获取股票价格.该抽象类如下所示

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

"""
Defines the abstract stock price reader
"""
from abc import ABC, abstractmethod
class StockPriceReader(ABC):
    """Defines the general tick reader interface."""
    @abstractmethod
    def get_price(self, symbol:str)->float:
        """
        Gets the price of a stock represented by the symbol, e.g 
        when symbol='AAPL', it gets the Apple Inc stock price. 
        """
        raise NotImplementedError

TickReaderConcrete类实现了内部细节,并通过类似于Bloomberg或交易所API调用的方式获取实际股票价格.进行API调用所需的凭据必须是内部细节的一部分.这里没有显示代码,因为它很容易实现.

Dilemma

现在,基于上面简单的类依赖关系图,同一本书(Clean Architecture)似乎暗示(这里我强调)

主块应该not even be aware表示TickReaderConcrete存在.

至少,这是我对这本书所说的,因为没有箭头从mainTickReaderConcrete,纠正我,如果我错了.

但是当我写main.py时,我不能假装TickReaderConcrete不存在,换句话说,main似乎忍不住知道TickReaderConcrete的存在,当代码看起来像

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

"""
The main function to invoke the stockprice reader
"""
from tickreader import TickReaderConcrete
...
if __name__ == '__main__':
    # This line gives rise to the alternative class diagram below
    reader=TickReaderConcrete(...) 

    # After initialised, we can use the interface permitted by the abstract base class
    reader.get_price(symbol='IBM')
Question

那么,如何确保main人不知props 体读者的存在呢?如果main根本不导入具体阅读器,它甚至不能实例化具体阅读器对象,抽象阅读器无论如何都不能初始化. 那么,如何基本上组织代码来正确实现上面的对象图呢?

Slightly Paraphrased Question

即使抽象基类公开了必要的公共方法,至少initialisation也需要知props 体子类的存在.具体子类能隐藏在抽象基类后面吗?请看另一个对象图,这是上面代码片段实现的.如何摆脱 break line ?

enter image description here

推荐答案

我已经有好几年没读过《Clean Architecture》了,但我想提出一个不同的解释.实际上,Dependency Inversion Principle(DIP)确实表明抽象不应该依赖于实现细节,而是相反.

定义一个高级接口或抽象基类,并用一个包含所有细节的具体类实现它,是解决此类问题的标准方法.

然后,DIP建议几乎所有的代码都应该针对高级抽象来编写.这意味着,如果你有需要调用get_price方法的域逻辑,应该给它一个StockPriceReader抽象对象来进行交互.

但是,这个规则有一个例外,因为you need to compose the object graphs somewhere,这通常是在__main__方法中.这就是创建具体类的一个实例的地方,然后将其传递给需要抽象类的所有其他代码.

Python相关问答推荐

使用Keras的线性回归参数估计

更改matplotlib彩色条的字体并勾选标签?

我在使用fill_between()将最大和最小带应用到我的图表中时遇到问题

Python中绕y轴曲线的旋转

如何在Python数据框架中加速序列的符号化

根据列值添加时区

计算分布的标准差

Python Pandas获取层次路径直到顶层管理

需要帮助重新调整python fill_between与数据点

使用Python和文件进行模糊输出

与命令行相比,相同的Python代码在Companyter Notebook中运行速度慢20倍

ruamel.yaml dump:如何阻止map标量值被移动到一个新的缩进行?

在matplotlib中使用不同大小的标记顶部添加批注

如何从pandas DataFrame中获取. groupby()和. agg()之后的子列?

在二维NumPy数组中,如何 Select 内部数组的第一个和第二个元素?这可以通过索引来实现吗?

freq = inject在pandas中做了什么?''它与freq = D有什么不同?''

Js的查询结果可以在PC Chrome上显示,但不能在Android Chrome、OPERA和EDGE上显示,而两者都可以在Firefox上运行

修改.pdb文件中的值并另存为新的

使用xlsxWriter在EXCEL中为数据帧的各行上色

将标签与山脊线图对齐