I have a class that represents a pretty complex object. The objects can be created by many ways: incremental building, by parsing text strings in different formats and by analyzing binary files. So far my strategy was as follows:
-
Have the constructor (
__init__, in my case) initialize all the internal variables toNone -
Supply different member functions to populate the object
-
Have those functions return the new, modified object to the caller so we can do
sd = SuperDuper().fromString(s)
For example:
class SuperDuper:
def __init__(self):
self.var1 = None
self.var2 = None
self.varN = None
## Generators
def fromStringFormat1(self, s):
#parse the string
return self
def fromStringFormat2(self, s):
#parse the string
return self
def fromAnotherLogic(self, *params):
#parse params
return self
## Modifiers (for incremental work)
def addThis(self, p):
pass
def addThat(self, p):
pass
def removeTheOtherOne(self, p):
pass
The problem is that the class becomes very huge. Unfotunately I am not familiar with OOP pattern designs, but I assume that there is a more ellegant solution for this problem. Is taking the generator functions out of the class (so that fromString(self, s) becomes superDuperFromString(s) a good idea?
What might be a better idea in your case is dependency injection and inversion of control. The idea is to create another class that has all of the settings that you are parsing out of all of these different sources. Then subclasses can define the method to actually parse it. Then when you instantiate the class, pass an instance of the settings class to it:
Doing it this way has the advantage of adhering more closely to the single responsibility principle which says that a class should only have one (likely to occur) reason to change. If you change the way you’re storing any of these strings, then the class has to change. Here, we’re isolating that into one simple, separate class for each source of data.
If on the other hand, you think that the data that’s being stored is more likely to change than the way it’s stored, you might want to go with class methods as Ignacio is suggesting because this is (slightly) more complicated and doesn’t really buy you much in that case because when that happens you have to change two classes in this scheme. Of course it doesn’t really hurt much either because you’ll only have to change one more assignment.