Refactoring a class method to be under an abstract base class and splitting the logic without changing the base class method signature?

huangapple go评论90阅读模式
英文:

Refactoring a class method to be under an abstract base class and splitting the logic without changing the base class method signature?

问题

我目前正在重新设计一个类,将其置于一个抽象基类之下。当前类具有一个名为 func 的方法,该方法执行一些与两个事物 AB 相关的逻辑。

在逻辑 A 过程中,它将一个大型数据集加载到一个字典中,比如 dataset,然后稍后在逻辑 B 中使用 dataset.keys(),但除此之外,AB 是彼此独立的。

我将创建一个另一个类,比如 another_class,它类似于 current_class,但这个类不需要 B,只需要 A。所以类似这样:

class another_class:
  def func(self):
    # 对A执行一些操作

然后,两者都将置于一个抽象基类 base 之下。由于两个继承的类都涉及到 A,我打算在基类中创建一个执行 A 的方法,比如 func_A。但我在想如何最好地处理这个问题,以使函数签名一致,同时避免为 B 重新加载 dataset

如果 another_class 也需要 B 的逻辑,我认为我们可以从 func_A 中返回 dataset.keys(),然后在 func_B 中使用它,但 another_class 不需要。

因此,我不知道是否有一种好的方法来使这一点一致,而不必为这些方法使用不同的签名。

所以在代码中,我有以下两个想法:

1)

class base:
  @abstractmethod
  def func(self):
    pass
  def func_A(self):
    # 对A执行一些操作并获取数据集
    return dataset.keys()

class current_class:
  def func_B(self, keys):
    # 对B执行一些操作
  def func(self):
    keys = self.func_A
    self.func_B(keys)

class current_class:
  def func(self):
    _ = self.func_A() # 返回值未被使用...

2)

class base:
  @abstractmethod
  def func(self):
    pass

class current_class:
  def func_A(self):
    # 对A执行一些操作并获取数据集
    return dataset.keys()
  def func_B(self, keys):
    # 对B执行一些操作
  def func(self):
    keys = self.func_A()
    self.func_B(keys)

class current_class:
  def func_A(self):
    # 对当前类执行与func_A相同的操作,并且不返回任何内容
  def func(self):
    self.func_A()

我不喜欢第一种设计,因为 func_A 只需要为其中一个子类返回值,而不需要为所有子类返回值。我也不喜欢第二种设计,因为我们必须在每个继承的类中分别实现 func_A,尽管它们是相同的方法,只是一个需要返回值,而另一个不需要。

英文:

I'm currently working on redesigning a class to be under an abstract base class. The current class has a method func that does some logic for two things, say A and B.

(note that all the code below is very simplified. There's a lot more functionality than what is shown)

class current_class:
  def func(self):
    # does stuff for A 
    # does stuff for B

During logic A, it loads a large dataset into a dictionary, say, dataset and later dataset.keys() is used for logic B, but other than that, A and B are independent of each other.

I will create an alternate class, say, another_class that is similar to current_class, but this class doesn't need B and only needs A. So something like

class another_class:
  def func(self):
    # does stuff for A

And then both will be under an abstract base class base. Since both inherited classes involves A, I plan on just creating a method in base class that does A, say, func_A. But I'm having trouble with figuring out the best way to approach this so that the function signatures conform and without having to reload dataset for B.

If another_class also needed the logic for B, I think we can just return dataset.keys() from func_A and use it in func_B, but another_class doesn't.

So I don't know if there's a good way to conform this without having different signatures for the methods.

So in code, I have the following two ideas:

1)

class base:
  @abstractmethod
  def func(self):
    pass
  def func_A(self):
    # does stuff for A and gets the dataset
    return dataset.keys()

class current_class:
  def func_B(self, keys):
    # does stuff for B
  def func(self):
    keys = self.func_A
    self.func_B(keys)

class current_class:
  def func(self):
    _ = self.func_A() # the return is unused...

2)

class base:
  @abstractmethod
  def func(self):
    pass


class current_class:
  def func_A(self):
    # does stuff for A and gets the dataset
    return dataset.keys()
  def func_B(self, keys):
    # does stuff for B
  def func(self):
    keys = self.func_A()
    self.func_B(keys)

class current_class:
  def func_A(self):
    # does same stuff as func_A for current_class, and doesn't return anything
  def func(self):
    self.func_A()

I don't like the first design because func_A only needs to return something for one of the subclasses and not for all of them. I also don't like the second design because we have to separately implement func_A in each inherited class even though they're identical methods, except one needs to return something and the other doesn't.

答案1

得分: 1

不必担心忽略主要用于其副作用的函数的返回值。只需在基类中定义func_A一次,然后让两个子类根据其需求适当使用它。

class Base:
    @abstractmethod
    def func(self):
        pass

    def func_A(self):
        # 为A执行操作并获取数据集
        return dataset.keys()


class Child1:
    def func_B(self, keys):
        # 为B执行操作
    def func(self):
        keys = self.func_A
        self.func_B(keys)


class Child2:
    def func(self):
        self.func_A()

如果func_A中有与Child2无关的内容,那么当然应将其拆分,以避免在Child2.func中执行不必要的工作。但仅仅返回一个值既不会占用太多时间,也不会占用太多空间,不应成为担忧。

英文:

It's not a big deal to ignore the return value of a function that is primarily called for its side effects. Just define func_A once in the base class and let both child classes use it as appropriate to their needs.

class Base:
    @abstractmethod
    def func(self):
        pass

    def func_A(self):
        # does stuff for A and gets the dataset
        return dataset.keys()


class Child1:
    def func_B(self, keys):
        # does stuff for B
    def func(self):
        keys = self.func_A
        self.func_B(keys)


class Child2:
    def func(self):
        self.func_A()

If there is more in func_A that isn't necessary for Child2, then it should of course be split up to avoid doing unnecessary work in Child2.func. But simply returning a value is not in anyway time- or space-intensive, and should not be a concern.

huangapple
  • 本文由 发表于 2023年2月14日 05:07:15
  • 转载请务必保留本文链接:https://go.coder-hub.com/75441193.html
匿名

发表评论

匿名网友

:?: :razz: :sad: :evil: :!: :smile: :oops: :grin: :eek: :shock: :???: :cool: :lol: :mad: :twisted: :roll: :wink: :idea: :arrow: :neutral: :cry: :mrgreen:

确定