bryanedds

This is kind of OT, but I'd like to see what the other developers here have to say.

I used implementation inheritance in Buttermilk's GUI design. I am regretting it quite a bit. I used implementation inheritance because I reasoned that everyone else's GUI system (including my past two) do so. But the more I learn about design and anti-patterns, the more subtle flaws I see arising because of the decision to use impl inheritance.

Why do people use impl inheritance, even when they know better I presume because it's just so darn easy and quick. There is no way a modern language could get away with getting rid of implementation inheritance completely. People wouldn't accept it. In my opinion, a new language without implementation inheritance is not what's needed. It seems to me that what is really needed is a language that makes containment almost as easy and quick to use as implementation inheritance. Consider that you have an interface with say, 10 methods. To use containment, you would often make a generic class which provides a default implementation for that interface, inherit the interface in a second class which contains an instance of the default implementation class, then map the inherited interface methods to call each of the default implementation object's respective methods. So you have to write 10 arbitrary method call mappers each time you make a new class. What if the interface had 30 methods What if you had to make 20 new classes using this technique That's 600 function calls that look approximately like this -

public override void ProcessFoo(Foo foo)

{

m_defaultImpl.ProcessFoo(foo);

}

Shouldn't a language take care of this sort of mapping for you automatically Maybe like this -

publc class Bar : IFooProcessor

{

private automap<IFooProcessor> IFooProcessor fooProcessor;

}

This is the type of language feature that could make containment so much easier to use that people would use implementation inheritance less and containment much more on their own.

Does that make sense to anyone




Re: XNA Game Studio Express Implementation Inheritance Regrets

Gunston

Bryan

I've found myself in this situation more than a few times.  Writing those one-line functions is depressing isn't it

I seem to remember an old Clipper (xBase language from the late 80's, early 90's) add-on OOP library (Class(y), I think) that supported declarative method/message forwarding of the type you describe (although no angle brackets!).  Clipper was an innovative language and had lambda functions (called code blocks and borrowed in turn from Smalltalk and in turn from somewhere else, I'm sure) way back then.

Method/message forwarding was achieved through some preprocessor magic.  For example, you could say (declaratively in your class definition):

MESSAGES ProcessFoo, ProcessBar, Wibble TO m_defaultImpl

Maybe what we need is a better pre-processor in C#.  No, cancel that thought.

Again, Clipper's pre-processor was the most powerful I've seen and you could write things like:

#command ADD <x> TO <y> GIVING <z> => <z> = <x> + <y>

to create new command statements so the following would compile OK.

local z;

ADD 10 TO 5 GIVING z

I'm reminiscing now and getting way OT.  This post should be read through a sepia filter.






Re: XNA Game Studio Express Implementation Inheritance Regrets

Joel Martinez

so you're saying that .NET should support multiple inheritance





Re: XNA Game Studio Express Implementation Inheritance Regrets

Jim Perry

Joel Martinez wrote:
so you're saying that .NET should support multiple inheritance

I'd love to see this. It would be especially useful in the RPG I've been toying with.






Re: XNA Game Studio Express Implementation Inheritance Regrets

Joel Martinez

hehe, don't hold yer breath :-P

Me personally I've gotten pretty comfortable with the single inheritance model. As long as you keep interfaces fairly small and granular, they are easy to implement. IMO, if you've got an interface that has 30 methods, you might want to rethink your design.

edit: now that I think about it, the one thing I would love to see, is the ability to define public Fields in an interface ... that would be awesome!

edit2: and while we're at it, let's add generic constraints for operator (+, -, *, /):-D





Re: XNA Game Studio Express Implementation Inheritance Regrets

dczraptor

You CAN define public fields in an interface:

int Health {get; set;}






Re: XNA Game Studio Express Implementation Inheritance Regrets

Joel Martinez

no no ... that's a public Property my friend. And when the property involves a struct, you can end up with subtle differences in the way it works, vs the way you expect it to work. Having public Fields would allow you to expose things as complex as a Matrix, while still working as one might expect.

edit: specifically, look at the answers to questions # 2 and 4 here:
http://blogs.msdn.com/ricom/archive/2006/09/07/745085.aspx





Re: XNA Game Studio Express Implementation Inheritance Regrets

dczraptor

Ah, my bad. Didn't know there was a major difference. Thanks for pointing that out to me. Now that I think of it, I've run into a related problem, where i exposed a Vector3 as a property, and tried to modify the x, y, and z values but it didn't let me.




Re: XNA Game Studio Express Implementation Inheritance Regrets

bryanedds

>> so you're saying that .NET should support multiple inheritance

Not really.

I'm saying that even single implementation inheritance is a bad thing. Multiple implementaiton inheritance would then be a multiply bad thing :)

Containment is almost always the better alternative to implementation inheritance currently is. What is needed is a language that makes containment as easy and as automated as implementation inheritance. Currently, to use containment as a replacement for implementation inheritance, you have to write a wrapper method for each interface method to forward the call to the contained component. Things like that should be taken care of you within the language automatically.

Now, I said that SI and MI are bad things. That doesn't mean they should be removed from the language. If people want to use flamethrowers to cook marshmallows, I say let them. What I am arguing for a language that makes containment so quick and easy that people voluntarily will choose to use it instead of inheritance.






Re: XNA Game Studio Express Implementation Inheritance Regrets

BrianOsman

Yeah, I'm starting to get really frustrated with the obstacles to doing things cleanly. I'd like to be using interface inheritance a lot, but it's often way too much work. Extremely simple example: I'd like to have a common interface for objects that have a 2D position.

OK, so I make an interface. I want everything that implements the interface to have a Vector2 member. I can't put that field in the interface, because that's obviously wrong (and not allowed). So I put a public Vector2 property in the interface. OK, now every derived class has to include a member for no good reason. What's worse, clients can't mutate the members of the Vector2 via the property, because of the wacky lvalue demotion thing that happens when you return structs through properties. Damn.

OK, so I have to add more public properties to the interface, like X and Y, which are implemented in terms of the Vector2 property. The code is becoming really ugly, and I'm not even trying to do something difficult. Where did I go wrong

The alternative (I guess) is that the position should be contained, not derived. (Which is fine, I don't mind that...). So I just add a Vector2 member to any class that needs it. Now I don't have a common base class, so I can't group things or do any useful RTTI. This is getting annoying. Next step: make a Vector2 wrapper class that will allow write-through when returned as a property, and then make the interface have a public property that returns one of those. Now I've lost all performance benefits of using a value type.

Seriously, have I missed some obvious better way of doing all this





Re: XNA Game Studio Express Implementation Inheritance Regrets

bryanedds

Most people bite the bullet and go for interface simplicity over performance. People put a Vector2 member in the interface and are done with it. I have done this as well with Buttermilk Game / GUI Engine. I considered using two floats in the interface instead of the Vector2s, but that's just not standard for the components that are released. I ultimately decided for Vector2's because of their prevelance in the 2D XNA community and components.

So, my advice is just use the Vector2s and don't concern yourself with the performance drawbacks. Using an extended interface to save performance quickly gets out of hand or out of the community standard that has spontaneously arose. It's a case of tradeoffs, and there's no one perfect answer in this case, I'm afraid.

This is a good case for the type of language feature thing I'm suggestion in general though.






Re: XNA Game Studio Express Implementation Inheritance Regrets

Gunston

Bryan

I think Brian's (is this a Bri/yan-only thread ) point is slightly different to the one you're responding to. It boils down to the fact that if you have a property that returns a Vector2 (whether that property is defined in an interface or not), modifying the Vector2 returned by that property has not effect on the original as a temporary copy is being made under the covers. This means you end up with additional properties (X and Y or PositionX and PositionY, for example) in the interface and implemented in the class to enable the user to modify one of the sprite's coordinates.

Only way to make this work is to resort (and I mean last resort) to pointers...

In Sprite class:

    unsafe public Vector2* PositionPtr
    {
      get
      {
        fixed (Vector2* p = &this.position)
        {
          return p;
        }
      }
    }

Elsewhere:

    unsafe
    {
      sprite.PositionPtr->X = 1000;
      Program.PrintVector2(sprite.Position); // ta-da!
    }

I'm not suggesting anyone do this, just that it's the only way to get to the original Vector2 struct through a property that I can think of.

By the way, I'm sure the multiple inheritance guys will say that multiply-inheriting from a notional Vector2 class and a notional DrawableObject class will solve all your problems. I would ask them to consider whether a sprite is-a DrawableObject (yes) and whether a sprite is-a Vector2 (no). Plus if you have other public Vector2-type properties such as Scale, the multiple inheritance approach quickly breaks down... is your sprite more a Position than a Scale

Back to your original point, I'm with you Bryan: abstract object factories and containment patterns are simpler to implement and maintain when programming in the large and that implementation inheritance (even in the small, well-understood universe of UI frameworks for example) is often a pain. It's just that current OOP languages don't handle containment well. Maybe this is something that could be addressed by AOP where method interception is inherhent and method forwarding (to your default implementation) could be trivially implemented.

Discuss.






Re: XNA Game Studio Express Implementation Inheritance Regrets

Hlubocky

Figured I would jump in with a question and add to the number of Brians in the thread...

You are saying that if you make a Vector2 a public member of the interface, then whenever someone needs to set a value on the property, they need to create an all new struct (is it still called instantiation if it is a struct ). Would this be worse performance-wise than if the Vector2 was a class whose members could be directly modified through the property I guess my question is, is there something different about constantly creating new value types versus constantly instantiating new class objects in terms of performance and garbage collection

--Brian




Re: XNA Game Studio Express Implementation Inheritance Regrets

Joel Martinez

Yes, creating new value types is a million times more preferable to creating new reference types (at least as far as during gameplay).

All of this would be solved if you could have Fields in interfaces, but until then, the best bet to support both performance, and an interface based design is to use methods to change your object's state.

And in some ways, this sort of makes sense ... does it make sense to expose a Vector2 from your Entity class, or does it make sense to have methods like .MoveTo(mapLocation), .PointAt(otherEntity).





Re: XNA Game Studio Express Implementation Inheritance Regrets

BrianOsman

Yeah, sorry I derailed this a bit, although I think all the issues are related. I'm still not totally convinced about implementation inheritance being bad, although that's really because I'm not sure how the alternative would work. If a language made containment simple and automatic, with some kind of access/method forwarding, you'd need some new concept that indicates whether or not a given type contains some other type. That breaks down though, because now you could contain more than one of that type.

I'm just referring to the loss of common ancestry from inheritance (interface or otherwise). If I could somehow make my position example be an interface like "IHasAPosition", then I could at least have a collection of objects that are all of type IHasAPosition. Containment has no analogous operation, unless you start going nuts with the reflection system: Iterate over all "object"s, get the type of each one, get the list of fields in each type, get the type of each field, if it's a position type ... yeah, nevermind.

I'm not trying to dump on containment, I think there is a better way to handle this, but the benefits of inheritance (mostly the ones provided by languages that encourage its use) are hard to ignore. Sadly, that still leaves me with no good solution to the incredibly simple problem of "I want a way to refer to and work with all objects that have a 2D position". The best compromise is the one above (Interface with a public property) which has TWO major problems:

  • I still have include a member variable in every class that implements the interface. Sure would be nice if I could put that in the interface, except then it would be implementation inheritance and I'm out of luck. Hmmm, actual multiple inheritance would come in handy right now.
  • I still have performance issues related to creating brand new Vector2s whenever I want to update the object. On Windows, I don't think I'd care. But with the brain-dead GC on 360, I'm trying to remain aware of these issues.