简体   繁体   English

设计调用其方法序列的 class 的最佳方法是什么?

[英]What's the best way to design a class that calls sequences of its methods?

I have a class similar to the one below where it goes through a series of methods using variables in the class. The code used to be a massive series of functions, passing variables around and this felt more structured and easy to work with/test.我有一个 class 类似于下面的代码,它通过一系列使用 class 中的变量的方法。代码曾经是大量的函数,传递变量,这感觉更有条理并且易于使用/测试。 However, it still feels as though there's a better way.但是,仍然感觉好像有更好的方法。

  1. Is there a better design pattern or approach for situations like this?对于这种情况,是否有更好的设计模式或方法? Or is going the object route a mistake?或者走 object 路线是错误的吗?

  2. In terms of testing process() and other methods, I can just mock the methods called and assert_called_once .在测试process()和其他方法方面,我可以模拟 called 和assert_called_once方法。 But, ultimately, it leads to ugly testing code with tons of mocks.但是,最终,它会导致带有大量模拟的丑陋测试代码。 So, it makes me wonder about question #1 again.所以,这让我再次想知道问题 #1。

class Analyzer:

    def __init__(self):
        self.a = None
        self.b = None

    def process(self):
        self.gather_data()
        self.build_analysis()
        self.calc_a()
        self.calc_b()
        self.build_output()
        self.export_data()
        ...

    def gather_data(self):
        self.get_a()
        self.get_b()
        self.get_c()
        ...
        
    def build_analysis(self):
        self.do_d()
        self.do_e()
        self.do_f
        ...

As for testing, and I know this code isn't technically right, but I just wanted to illustrate how it gets hard to read/sloppy.至于测试,我知道这段代码在技术上是不正确的,但我只是想说明它是如何变得难以阅读/草率的。

        
class TestAnalyzer: 

        
    @patch.object(Analyzer, 'gather_data')
    @patch.object(Analyzer, 'build_analysis')
    @patch.object(Analyzer, 'calc_a')
    @patch.object(Analyzer, 'calc_b')
    @patch.object(Analyzer, 'build_output')
    @patch.object(Analyzer, 'export_data')
    def test_process(self, m_gather_data, m_build_analysis, m_calc_a,
                     m_calc_b, m_build_output, m_export_data):

        analyzer.process()
        m_gather_data.assert_called_once()
        m_build_analysis.assert_called_once()
        m_calc_a.assert_called_once()
        ...

Any insight or thoughts would be appreciated.任何见解或想法将不胜感激。 Thank you!谢谢!

Maybe the information expert design principle can help you或许信息专家设计原理可以帮到你

Assign responsibility to the class that has the information needed to fulfill it将职责分配给具有履行职责所需信息的 class

In your example it seems like you can split your class into different ones with better defined responsibilities.在您的示例中,您似乎可以将 class 拆分为具有更好定义的职责的不同部分。 Assuming that you have to perform the following functions in order:假设您必须按顺序执行以下功能:

  1. Gather data收集资料
  2. Preprocess it预处理它
  3. Analyse it分析一下

I would create a class for each of them.我会为他们每个人创建一个 class。 Here you have some example code that generates some data and performs some basic calculations:这里有一些示例代码可以生成一些数据并执行一些基本计算:

from random import randint
from dataclasses import dataclass

@dataclass
class DataGatherer:
    path: str
    def get_data(self):
        """Generate fake x, y data"""
        return randint(0, 1), randint(0, 1)

@dataclass
class Preprocessing:
    x: int
    y: int
    def prep_x(self):
        return self.x + 1
    def prep_y(self):
        return self.y + 2

@dataclass
class Calculator:
    x: int
    y: int
    def calc(self):
        return self.x + self.y

All I have done is to divide your code into blocks, and assigned methods and attributes to fullfill the functions of those blocks.我所做的只是将您的代码分成块,并分配方法和属性来完成这些块的功能。 Finally, you can create an Analysis class whose only responsibility is to put the whole process together:最后,您可以创建一个Analysis class,它的唯一职责就是将整个过程放在一起:

@dataclass
class Analysis:
    data_path: str
    def process(self, save_path: str):
        x, y = DataGatherer(self.data_path).get_data()
        print("Data gathered x =", x, "y =", y)
        prep = Preprocessing(x, y)
        x, y = prep.prep_x(), prep.prep_y()
        print("After preprocessing x =", x, "y =", y)
        calc = Calculator(x, y)
        result = calc.calc()
        print("Result =", result)
        self.save(result, save_path)
    def save(self, result, save_path: str):
        print(f"saving result to {save_path}")

In the end this is all you have to do:最后这就是你所要做的:

>>> Analysis("data_path_here").process("save_path_here")
Data gathered x = 0 y = 1
After preprocessing x = 1 y = 3
Result = 4
saving result to save_path_here

When it comes to testing I use pytest .在测试方面,我使用pytest You can create a test file for each of your classes (eg test_datagatherer.py, test_preprocessing.py...) and have a unit test function for each of your methods, for example:您可以为每个类创建一个测试文件(例如 test_datagatherer.py、test_preprocessing.py ...),并为每个方法进行单元测试 function,例如:

from your_module import Preprocessing

def test_prep_x():
    prep = Preprocessing(1, 2)
    assert type(prep.prep_x()) is int

def test_prep_y():
    prep = Preprocessing(1, 2)
    assert type(prep.prep_y()) is int

I will leave you to pytest documentation for more details.我将留给您 pytest 文档以获取更多详细信息。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

相关问题 使用 class 在其方法中包含无限循环的最佳显式和隐式方法是什么? - What is the best explicit and implicit way to use a class contains an infinite loop in its methods? 装饰Python类方法的最佳方法是什么? - What is the best way to decorate methods of a Python class? 将 SCPI 命令树结构实现为 Python 类方法的最佳方法是什么? - What's the best way to implement an SCPI command tree structure as Python class methods? 在python中设计类的最佳方法 - Best way to design a class in python Python-在另一个类中对方法进行单元测试的正确方法是什么? - Python - What's the proper way to unittest methods in a different class? 在不同长度的批量序列上训练 LSTM 网络的最佳方法是什么? - what is the best way to train an LSTM network on batches of sequences with different lengths? 在 python 源文件中对类定义进行排序的最佳方法是什么? - What's the best way to sort class definitions in a python source file? 在python3中初始化类属性的最佳方法是什么? - What's the best way to init class attribute in python3? 检查类实例变量是否在 Python 中设置的最佳方法是什么? - What's the best way to check if class instance variable is set in Python? 设计和更改GTK界面的最佳方法是什么? - What is the best way to design and changing GTK interface?
 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM