lundi 13 février 2023

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

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.

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()

class current_class:
  def func(self):
    _ = self.func_A() # the return is unused...
    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()
    
    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.

    Aucun commentaire:

    Enregistrer un commentaire