2

Background

I'm a scientist and trying to incorporate better software development practices in my work. In my niche field there's a standard model everyone uses that accepts a whopping 56 arguments. I'm attempting to create a public toolset that helps create and organize all the necessary inputs. The motivation is twofold: 1. it's really difficult to keep track of 56 variables before calling the model and 2. I can provide improved error handling to help track down the problem before the model is called (if you give the model a bad input, it just says "there was a bad input..." which is frustrating to say the least).

To do this, I'm thinking I should make classes that acts like structs---that is, they accept inputs and validate them, but don't do anything with these inputs. Once one of the inputs is created, it never needs modified and will rarely ever need to be accessed when creating the other inputs. I've organized all of the inputs into categories, and it seems sensible to me that each category should be its own class (correct me if I'm wrong, but that's not the meat of the question).

Question

This model needs 4 different angular inputs to run. Any user of this model will almost never have all 4 of these inputs; rather, they'll almost always have something that can can easily be manipulated into the expected inputs. With this in mind, I think it would be best to design this class to do absolutely no manipulation, and simply add functions that can do the manipulations and return instances of the class. I think this would best adhere to the SRP. Is this a sensible idea, or am I being overly pedantic about things? Here is a sketch of my idea:

import numpy as np

class Angles:
    def __init__(self, angle0, angle1, angle2, angle3):
        self.angle0 = _Angle0(angle0)   # _Angle0 will validate the input 
        self.angle1 = _Angle1(angle1)
        ...

def convert(angle0, angle1, angle2, angle3):
    foo0 = np.cos(angle0)
    foo1 = np.cos(angle1)
    return Angles(foo0, foo1, angle2, angle3)

I guess it just feels wrong to have a class that does nothing but validate and store values, whereas the functions do all of the actual work of creating the inputs that I need. Can anyone comment on whether this is sensible or if there's an obviously superior way to design this basic code?

3
  • 1
    You're about to walk into a minefield... view one, view two, many other articles available. Commented Aug 23, 2021 at 20:50
  • 1
    I agree with Doc Brown's answer below; for your purposes, this is all mostly fine, just strive to express as much semantics as possible in the names of the types and methods rather than in comments. And have someone other than you try out your code and give you feedback - what feels natural to you might not make sense to others. While we can certainly offer some useful advice, many software engineering practices are motivated by challenges (like software evolution and maintenance in presence of a large user base) that aren't necessarily going to be particularly impactful for what you're doing. Commented Aug 23, 2021 at 23:43
  • A bit tangential to the question, but you may find pydantic useful for data/settings validation.
    – jfaccioni
    Commented Aug 26, 2021 at 14:56

1 Answer 1

4

it just feels wrong to have a class that does nothing but validate and store values

For me, it feels perfectly fine - as long as you can come up with a meaningful name for the class, one which lets you think of the group of parameters "as a whole", without always having to remember what's inside. I don't know your domain, but Angles sounds pretty meaningless to me - but maybe it is just so inexpressive for the sake of this example, not in the real code. Same holds for convert - give the function a name which expresses clearly what kind of conversion it does - from what input to what output. And the comment behind _Angle0 indicates the method should have a name like _validateAngle0, for example.

Additionally, consider to implement the conversion functions as class methods of Angle. It is probably not possible to implement them as different Angle constructors, since they are cannot be distinguished just by their signature, so class methods should be the canonical choice here.

Note that if you cannot come up with a better name for this group of four angles, that might be a sign that you chose the wrong abstraction.

1
  • I appreciate the feedback! Yes, I used non-descriptive names for the sake of the example but your assertion at the end is particularly useful. I think my code is more readable already.
    – coney1
    Commented Aug 26, 2021 at 1:26

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.