Good design for arguments that relate to a single configuration

Home / Uncategorized / Good design for arguments that relate to a single configuration

Question:
Suppose we have a class that represents a box:class Box:pass

It’s constructor may take some arguments which represent an object, for example length, width and height:class Box:
def __init__(self, length, width, height):self.length = length
self.width = width
self.height = height

Now I want to add a possibility to add shadow for the box, but it has to be optional, suppose shadow can be described with shadowcolor and shadowstrength. There are 3 ways how to add arguments that describe shadow to the constructor:class Box:
def __init__(self, …, drop_shadow=False, shadowcolor=None, shadowstrength=None):if drop_shadow:pass

This is the most explicit way, but drop_shadow here is a bit redundant, because we can just check if shadowcolor and shadowstrength are not None and set shadow to box:class Box:
def __init__(self, …, shadowcolor=None, shadowstrength=None):if shadowcolor and shadowstrength:pass

We dropped a redundant argument but now possibility of adding a shadow is more implicit.

Another approach would be to have a single argument – shadow that is a tuple of 2 arguments, where first one is shadowcolor and the other is shadowstrength:class Box:
def __init__(self, …, shadow=None):self.shadowcolor = shadow[0]
self.shadowstrength = shadow[1]

Now we have a single argument, but the level of implicitly is even higher.

I care about this so much because this will be used in opensource package and I want to make to make usage of a class as easy as possible.

How would you recommend to deal with this sort of ‘in-constructor’ configuration of another object?


Answer:
Have your function accept a dictionary for all of the params. For example

Create:parameters = {"dropShadow": true, "shadowColor": "#019201"}

Pass that through
def __init__(self, length, width, height, params):self.length = length
self.width = width
self.height = height

for key, value in params.items():if key == "dropShadow":self.dropShadow = value
elif key == "shadowColor"
self.shadowColor = value

If you don’t want to use hardcoded string (which i wouldn’t suggest) then create a shape model class that defines all of the properties as static variables. for example
class ShapeModel:DROP_SHADOW = "dropShadow"
SHADOW_COLOR = "shadowColor"

Then replace the above code with
def __init__(self, length, width, height, params):self.length = length
self.width = width
self.height = height

for key, value in params.items():if key == ShapeModel.DROP_SHADOW:self.dropShadow = value
elif key == ShapeModel.SHADOW_COLOR:self.shadowColor = value
Read more

Leave a Reply

Your email address will not be published. Required fields are marked *