Hi, I'm going to try and keep this as general as possible. I'm building an object model/API for creating and working with 'things' (I'm actually working with a 3D application through COM, so I guess I'm making a kind of middleware or wrapper interface). I'm looking for some advice on structure and encapsulation regarding creation vs. access. Links to reading material or replies would be greatly appreciated!
The primary job of the system is to automate many steps in the creation of 'things' , but because the 'things' are hierarchical, they are also used heavily for access (to create other things, output meta- data, etc.). For example, I might have a tree like: - root - thing(s) - thing(s) - thing(s) ...where "thing(s)" are objects of various types which share the same base class. Usage is pretty simple, even in the real system: >>> root = get_root() >>> thing_a = root.add_thing(type="a", name="thing a", ...) # factory >>> thing_b = thing_a..add_thing(type="b", name="thing b", ...) >>> print thing_b.name 'thing b' and access... >>> root = get_root() >>> thing_a = root.things["thing a"] >>> print thing_a.name 'thing a' >>> print thing_a.things ['thing b'] Now I start to get in to the problem at hand. Where is the best place to put the code that creates 'thing's. Right now I have a class for each type which takes the name to instantiate the class (find and wrap the 'thing'), but I've kept the class separate for access only. For creation I use a function (which is called by the factory method shown above) which creates the 'thing' and then returns an instance of the type class (note that in the real system, creation takes many parameters), e.g.: def new_type_a(name, **kwargs): thing = application.create_thing(name) # COM object method return TypeA(thing.name) This seems pretty simple and clean, but the more complex my package becomes, the less flexible this becomes. For example, I need to create 'thing's which are actually made from totally different objects in the COM application but still run common code to make it one of my types. I think an analogy is in order. Lets say I want to create a 'thing' which is a kind of desk. All desks get 4 legs, but some are made from oak and some from pine which have different properties. The different types might be a different color or other cosmetic extra. So the creation chain would be: pine --> desk --> desk_a oak --> desk --> desk_a pine --> desk --> desk_b oak --> desk --> desk_b At first it may seem strange to make desk_a out of different chains. Shouldn't it be two different types? In my case no, because the type class doesn't need to know which wood it comes from. The 'user' of the desk will intuitively know which one they want and even if they don't, they can easily check for it. The inheritance has to work this way because (still using the analogy) 'pine' and 'oak' are objects native to the COM accessed application while the 'desk' and desk types are mine. To accommodate this, I've had to add functionality between creation and returning the class. I'm not sure what to call these. Mutators? Constructors? Anyway, to implement this I actually add separate factory functions for each archetype ('pine' or 'oak in the analogy) which each run the same functions *after creation*. Something like: >>> root = get_root() >>> # These would have different arguments in reality... >>> thing_a = root.add_pine_thing(type="a", name="thing a", ...) # pine >>> factory >>> thing_b = thing_a.add_oak_thing(type="a", name="thing a", ...) # oak >>> factory If the analogy is just confusing things, in real terms, I might use one factory to create a 3D object which represents a point in space and another to draw a curve. Both of these might result in a type which is used for the same purpose in the 3D application (the end user doesn't care what it is made out of as long as it does it's job). I hope this all makes sense and gives enough background... The questions are: Should the code which creates the 'things' be encapsulated in the 'thing's class or in a chain of functions? Is there some design pattern in Python which would allow me to create a new 'things' in different ways or access existing 'things' with the same class, without dirtying the instance name-space (since the 'user' will use an instance for access, but the 'system' would use it for creation)? Or something else? Let me know if I can clarify anything. This seems like a basic design question when dealing with things created and accessed by an object model, but the devil is in the details. Thanks for reading, - Rafe -- http://mail.python.org/mailman/listinfo/python-list