Question

I'm trying to understand when it is better to pass explicit arguments to a method and when it is better to just pass self. I created a little example to illustrate the question.

Here are two different class methods that do the same thing:

def get_my_colors(self):
  colors = []  
  for obj in self.layers:
        colors.append(self.color_converter_dict[obj])
  return colors


@staticmethod
def get_my_colors(layers, color_converter_dict):
  colors = []  
  for obj in layers:
        colors.append(color_converter_dict[obj])
  return colors

I would like to understand the pros and cons of each. It seems to me that the first is hard to test because I have to instantiate an instance of the class (which is not trivial in my case) then test the method. The second is much easier to test but there is a downside in that calling it is more verbose. The first could be called with my_colors = self.get_my_colors() while the second would be my_colors = self.get_my_colors(self.layers, self.color_converter_dict). If I'm interpreting this answer correctly, if layers and color_converter_dict are intrinsic properties of self (which they are in my case), they don't need to be passed and the first method is preferred. However, my intuition is that the second approach is better because it is easier to test.

Was it helpful?

Solution

Passing arguments to a method, where each argument is part of self, is an immediate code smell:

my_colors = self.get_my_colors(self.layers, self.color_converter_dict)

If using an object, why would you not use the object? This is much cleaner, easier to understand and write:

my_colors = self.get_my_colors()

This part of your question is the real problem you are trying to solve:

It seems to me that the first is hard to test because I have to instantiate an instance of the class (which is not trivial in my case) then test the method.

The method is difficult to test because the class has complicated dependencies. You are trying to solve the wrong problem. Instead focus on isolating some of the logic in their own classes, which have few dependencies and are easier to test. Utilize dependency injection properly, along with proper test stubs or mocks to make testing the original object easier.

Licensed under: CC-BY-SA with attribution
scroll top