I have a class with a complex construction process with many parameters. Multiple clients share objects of this class, and the union of these clients parameters are used to instantiate the class. Therefore I have a factory class that stores these requirements, checks consistency of the various clients' requests, and instantiates the class.
Additionally, there are a common set of use models (or sets of parameters) which multiple clients use for multiple factories.
For instance, consider an example. (Note that the actual code is C++, but my experience is in Python so I'll pseudo-code in Python. Yes, I know that this example wouldn't actually work as-is.)
class Classroom:
def __init__(self, room_size=None, n_desks=None, n_boards=None,
n_books=None, has_globe=False, ... ):
...
class ClassroomFactory:
def __init__(self):
self._requirements = dict()
def addRequirement(self, name, value):
if name.startswith("n_"):
self._requirements[name] = max(value, self._requirements.get(name, 0))
...
def createClassroom(self):
return Classroom(**self._requirements)
# instantiate the factory
factory = ClassroomFactory()
# "client 1" is a geography teaacher
factory.addRequirement("n_desks", 10)
factory.addRequirement("n_boards", 1)
factory.addRequirement("has_globe", True)
# "client 2" is a math teacher
factory.addRequirement("n_desks", 10)
factory.addRequirement("n_boards", 1)
# "client 3" is a after-school day-care
factory.addRequirement("room_size", (20,20))
factory.addRequirement("has_carpet", True)
room = factory.createClassroom()
The common use model is as a teacher, we need 10 desks and a board. I think this is best served by a non-member function/decorator, something like:
def makeTeacherRoom(factory):
factory.addRequirement("n_desks", 10)
factory.addRequirement("n_boards", 1)
return factory
This seems like a great example of the "prefer non-member/non-friend to member" paradigm.
The thing that I'm struggling with is, within the framework of a much bigger OO code, where should these types of non-member functions/decorators live, both in terms of namespace and in terms of actual file?
Should they live in the factory's file/namespace? They are closely related to the factory, but they're limitations on the general factory, and need not be used to use the factory.
Should they live in the client's file/namespace? The client understands these use models, but this would limit re-use amongst multiple clients.
Should they live with a common base class of the clients (for instance, one could imagine a "teacher" class/namespace which would also provide the non-member function makeTeacherRoom(), which would be inherited by MathTeacher and GeographyTeacher.
Should they live somewhere else completely, in a "utils" file? And if so in which namespace?