views:

139

answers:

3

My project involves Qt plus and unnamed 3rd party physics simulation library. The way the physics library works is that physical bodies cannot create themsleves; the "world" must instantiate them so that they can be added to the world immediately.

My project creates a wrapper around these physical bodies to add some extra functionality, but because it stores these physical bodies it can't be instantiated either. The first question is, does it make more sense to allow these bodies to stand on their own? The part that I find awkward is that I have to pass a reference to the world to the object so that it can be created, when, to me, it makes more sense to pass the object to the world.

To fix this, I can delay the creation of the 3rd party body until it is added to my world wrapper. But that means my world wrapper becomes in charge of initializing the body correctly. It also means that I can't really access any of the properties of the object until it's added to the world anyway, because they all rely on the 3rd party body being initialized... unless I duplicate all that data and then pass it off to the library when it's added.

Is it worth the effort, or should I just continue to pass a pointer to my world wrapper so that my body wrapper can be created?

I mention Qt, because the way the Qt graphics framework works is that you can create QGraphicsItems whenever you want, and they'll stand on their own, but they just won't be visible until you add them to the scene. The analogy here is that GraphicsItem == Body, and Scene == World.

+2  A: 

To be truely effective, a facade pattern (your wrapper) has to hide the underlying details of the implementation from the user of the facade. This does mean using data transfer objects to hold the data. Facades can be cumbersome to implement but they give you the ability to change out the underlying implementation without affecting the end user.

sudo code:

Rock rock = new Rock(100); //simple data container for now.

PhysicsFacade f = new PhysicsFacade(); //internally creates world.

f.DoSomething(rock); //internally rock's data used by world to create an equivalent    object which is attached to the rock data container for future use.
Joe Caffeine
So... you're saying I *should* store everything in tmp variables until the body is fully initialized... then all my getters and setters basically need to check "has the body been initialized yet?"
Mark
It all depends on how the implementation is being used. Since this world object is responsible for creating the bodies it could be initalized inside the first call to the facade.
Joe Caffeine
But then the facade (body wrapper) is still controlling (creating) the world and can't exist independently of the world... you're suggesting the same thing as ChrisW it seems?
Mark
The idea of the facade pattern is that it hides the underlying implementation details from a user of the facade's API which should be cleaner than the one below it. As the coder of said facade, you still have to deal with all the messy details but your users (even if you are the user) are shielded from it.
Joe Caffeine
+1  A: 

all my getters and setters basically need to check "has the body been initialized yet?"

If you're using Qt I suppose you're using C++.

I don't know Qt and I don't know why you want to change the existing mechanism, but anyway: one thing you can do in C++, that may be useful to you, is overload the -> operator to access your objects. When someone invokes the -> operator, the operator can also create the object just-in-time if it hasn't already beein instantiated, something like:

World& getWorld();

class Body;

class MyWrapper
{
  Body* m_body;

public:

  MyWrapper() : m_body(0) {}

  Body* operator->()
  {
    if (!m_body)
    {
      m_body = new Body(getWorld());
    }
    return m_body;
  }

  ... etc ...
};


Edit

What do you mean, "change the existing mechanism"? The one that the physics library has laid out? I think I mentioned my reasons.

Yes.

With your solution... what does getWorld() do? Is that a global function? If world is floating around in global space, then there isn't really a problem, I can just instantiate the body at the same time MyWrapper is instantiated.

Yes it returns a reference to the World, which is what you need to create a body in the physics library. It's an example, I don't know where you're getting your World reference from, nor when.

But what if the world still doesn't exist at the point that the -> operator is used? I'm not really sure this solves anything. Not to mention that one way or another, you're still passing the world to the body

Maybe getWorld will throw an exception if it's called too early. Anyway, what this was supposed to buy you was:

  • The ability to create your MyWrapper instances without a World reference and perhaps before the world is created.

  • The ability to create a Body instance just-in-time when a client tryied to access any of the Body's propeties or methods

The -> operator is what clients would using to get at the physics body which you're wrapping: like a "smart pointer".

It might be easier to understand and/or to suggest solutions for your problem if you'd illustrate your problem with some pseudocode.

Not to mention that one way or another, you're still passing the world to the body

You said that was a requirement of the underlying library. When you said, "Should I attempt to fix", I thought you meant "Shall I implement a different API in my wrapper, and hide the existing API within the my private implementation?" It didn't occur to me that you might try to change (not just wrap) the existing implementation.

ChrisW
What do you mean, "change the existing mechanism"? The one that the physics library has laid out? I think I mentioned my reasons. With your solution... what does `getWorld()` do? Is that a global function? If `world` is floating around in global space, then there isn't really a problem, I can just instantiate the body at the same time MyWrapper is instantiated. But what if the world still doesn't exist at the point that the `->` operator is used? I'm not really sure this solves anything. Not to mention that one way or another, you're still passing the world to the body...
Mark
Nono... I don't mean change the existing implementation. It's still possible to create the BodyWrapper without one single reference to the world. It just means someone else will have to finish the creation of the object... but we can tuck that away somewhere where no one has to see it :) I don't want the world to be in global space... so that means getWorld() has to be a member of some class... which means I have to somehow pass that class to the wrapper... which takes us back to where we started. That's my point. I do appreciate your thoughts, but let me share what I've come up with...
Mark
A: 

Before I share my answer, let me rename a few things. "Object" is the thing that holds the "physics body". "World" is the thing that holds the "physics world". Again, only the "physics world" can create the "physics body" (its constructor is private).

Here's what I've done. The Object simply holds a pointer to the physics body. That way you can create Object whenever you want, and play with all it's data without even needing a world... you just can't touch the properties directly related to physics body (I'm going to ASSERT this).

The World finishes instantiating the Object (ie the physics body) as soon as it's added to the World. This perhaps breaks a tiny bit of OOP because the world has to manipulate a few of the Objects varibales to do so (I've made it a friend) but I think it's the least of the evils.

Mark