1

What's the cleanest and most coherent way to assign a new value to an object field when the calculation of that value is outsourced to another method?

The most obvious way would just be to update the field value when it's calculated in the method, as so: [examples in Python]

class MyClass:
  def __init__(self, arg):
    ...
    self.calc_values(arg)
    ...

  def calc_values(self, arg):
    ...
    self.var1 = value1
    self.var2 = value2

...but I feel like this doesn't give very traceable code, as I don't like the idea of updating values 'in the background'. My preference is to do something like this:

class MyClass:
  def __init__(self, arg):
    ...
    self.var1, self.var2 = self.calc_values(arg)
    ...

  def calc_values(self, arg):
    ...
    return value1, value2

Although this feels wrong, since the fields could just be set directly in the object method, hence I sometimes do this:

class MyClass:
  def __init__(self, arg):
    ...
    self.var1, self.var2 = self.calc_values(arg)
    ...

  @staticmethod
  def calc_values(arg):
    ...
    return value1, value2

Which one of these is generally preferred, or is there a better way entirely?

2
  • does whatever language this is have properties?
    – Ewan
    Feb 3, 2023 at 13:55
  • The examples given are in Python. It does, but I'm not sure I see how they could help in this case?
    – Lord Cat
    Feb 3, 2023 at 14:36

2 Answers 2

2

If possible, I prefer pure methods, i.e. your option 3. These methods tend to be easier to read and understand since they only use the input arguments, and does not have any side effects.

However, that is not always practical, so in some cases your option 1 might be preferable. But in that case I would call it something like update_values to make it clearer that this is not only calculating values, but also have side effects.

The important thing in my opinion is making your code clear and easy to understand.

1
  • Thanks, it's good to know that they're valid approaches and that I'm not doing anything too wierd. I also like option 3, it still seems like a strange way to do it though - i.e. not really how a class is designed to be used.
    – Lord Cat
    Feb 3, 2023 at 16:02
1

I feel that with modern development environments (IDEs), your concern about updating things "in the background" is not really much of an issue, as most editors allow a functionality along the lines of CTRL + clicking a function name to navigate to the declaration.

Granted, the rules of clean code still apply.

class MyObscureClass:

    def __init__(self, args):
        self._initialize_values(args)

    def _initialize_values(self, args):
        self.x1 = args.x1
        self.x2 = args.x2
        self.y1 = args.y1
        self.y2 = args.y2

is not as comprehensible as something like:

class LinePlotter:

    def __init__(self, args):
        self._set_line_coordinates(args)

    def _set_line_coordinates(self, args):
        self.x1 = args.x1
        self.x2 = args.x2
        self.y1 = args.y1
        self.y2 = args.y2

the key difference being that the method being used to set the values has been descriptively named according to what it's doing. You want to avoid vague method names like initialize_values or process_inputs. What are you initializing them to? Why are you initializing them? Processing inputs how? What are the inputs?

Focusing on these will make your code strides better than worrying about where to call the functions will.

Happy coding!

1
  • 1
    Thank you, that's good advice!
    – Lord Cat
    Feb 3, 2023 at 15:59

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Not the answer you're looking for? Browse other questions tagged or ask your own question.