Sorry for being so prescriptive in my first email about interfaces and
mocking and starting a bit of a side discussion about interfaces Vs
abstract classes. It smells a little like a no-one-right-answer
discussion that has probably been debated in every API forum.

I think most people could live comfortably with each approach.
However, I've seen many cases of frameworks starting out with abstract
(or concrete) classes and then going through pain of introducing
interfaces when the problems crop up. I think it would be a shame to
go the other way. GWT is going through to the trouble of introducing
IsWidget, etc., presumably to support better composition. In GWT's
case that's always smelled to me like something that might have been
done differently if the designers could start with a clean slate. If
the convention in GWT it to have Is{Abstract|Concrete} and a default
implementation of the interface then it might be worth moving to that
model for consistency, but that would probably break even more code!

The Interface Vs AbstractClass discussion so far seem to break into
the two main points:
1) Multiple inheritance.
2) Mocking

My view:

1) Multiple Inheritance:
I think the problem usually comes down to: What if a developer class
naturally behaves like an Activity and a "something-else", where
"something-else" is written in some framework the GWT team have no
control over and also requires you extend another Abstract class.
Well, then we get into writing shims like getAsActivity(),
getAsSomethingElse() to get around the Java single inheritance model.
With interfaces, internally, the implementer may well be using
delegation/composition to avoid writing the same code again. Use of
inheritance for code re-use rather than true specialization is
convenient, but I've become less tolerant to it over time when it is
presented as the only way to do things (rather than a convenience)
because it seems to cause a lot of pain.

2) On the mocking point - perhaps everybody uses EasyMock now and
that's ok. My understanding is that EasyMock won't work under standard
GWT tests (somebody please correct me if I'm wrong). The class
extension code is, IMO, a clever way of mocking classes that were not
written with an API / testing in mind. Having previously measured the
performance impact of mocking classes Vs interfaces I can tell you
there was at one point a measurable several-order-of-magnitude
difference in performance. I don't know if that's still the case but
the reason we looked at it at all was that our small tests were taking
many seconds to run and we couldn't work out where all the expense
might be coming from. That's not a compelling argument backed up by
evidence but something people might want to debunk if using mocking-of-
classes extensively.

I guess Activity may be so simple this isn't something that I should
be concerned about, but having had to hand-roll stubs/fakes/mocks for
classes that were never designed for testing in mind (and also not
very amenable to EasyMock-style expectation-setting) I tend to have a
knee-jerk "interfaces are good, abstract classes are bad" reaction.
One problem is, if somebody adds a method to AbstractActivity and I'm
hand-rolling test classes there's no compile time error to say that
I've forgotten to override a method and so my AbstractActivity is now
only partially mocked. Those can be fun to debug. The "easy to evolve"
advantage of an abstract class actually causes problems in this one
case.

The other problem for me is that if you have the following:

new MyClassUnderTest(fooActivity)

And fooActivity is of type FooActivity. The developer made it an
interface because a mocking framework didn't fit, or because that's a
project standard, or they wanted a fake, not a mock or a stub. The
internals of MyClassUnderTest cannot then take FooActivity and pass it
to something expecting an AbstractActivity (without a nasty, test-
breaking cast) even if the developer has go to the trouble of
declaring identical methods on FooActivity as are inherited from
AbstractActivity. I've hit this a few times and had to resort to
EasyMock-class extension, or the "override everything" approach to
writing mocks.

Just my 2c.

Neil.

-- 
http://groups.google.com/group/Google-Web-Toolkit-Contributors

Reply via email to