Interface-oriented programming and Noop

2 views
Skip to first unread message

Lindsay Smith

unread,
Sep 25, 2009, 8:59:32 PM9/25/09
to Noop
Hi,

Some of the design principles that you list for Noop caught my
interest as they intersect with my own ideas about better ways to
structure code. In particular:

Avoiding inheritance - I share your distate for subclassing as a
modelling construct when in fact subtyping (interface inheritance) is
modelling, subclassing is only ever code reuse.

Writing code using interfaces is a much more powerful way of going
about it, and you seem to have picked up on this in the areas of
automatic testability (every class is an interface), and in the
discussions about object binding scopes, because if everything is an
interface, you need some way to get an instance, which suggests the
factory pattern, but where does the factory come from etc etc....

There are some other areas that I consider important to interface
oriented programming that I'd like to share to see if any of them
align with your project goals.

1. Automatic delegation with overrides

You already cover this somewhere, but being able to say that an
interface is implemented by a class where it passes the methods
through to a delegate automatically, apart from some methods you'd
like to alter:

Class foo implements bar {
bar _delegate

void someMethod() {
.. do something instead of calling someMethod on _delegate
}
}

2. Ability to specify the interface method you are
implementing. .NET has this and is very useful if you have a class
that implements two interfaces that share a method signature:

Class foo implements bar, bang {
void getInfo() implements bar.getInfo {}
void getInfo() implements bang.getInfo {}
}

This means that method dispatch is dependent on the type that the
caller believes you to be. I think this is very useful as I view
casting an object to an interface as equivalent to requesting a
capability, and therefore the class needs to know what capability is
being asked for in each method.

3. Events as first class API types

.NET has an event type, which can form part of your interface. Very
useful for observor stuff.


4. An IUnknown type mechanism for requesting an interface of a
class.

In many component-based systems it is useful to ask an Object whether
it supports some kind of interface. For example, determining if an
Object supports being rendered, or persisted. The 'instanceof' test
in Java is clumsy as it requires the object to directly implement
every interface it needs to support. The IUnknown system is very
useful, in Java it translates as:

T <T> queryInterface(Class<T> clazz) {}

Which an object may implement to return a delegate object when
requested for particular interfaces e.g.:

T <T> queryInterface(Class<T> clazz) {
if (clazz.equals(Renderable.class)) {
return _myRenderingAdapter;
}

}

This provides much finer control over how an Object at runtime chooses
to implement a contract that may be requested of it.

Additionally, the use of the decorator pattern is a key part of
interface oriented programming. By wrapping an Object with another
implementor of the same interface, we can do logging, security
checking, or whatever to modify the inner class's behaviour. However
this means that the outer class is then the target of any 'instanceof'
tests that may be intended for the inner class. By using the
queryInterface mechanism above, the decorator can delegate requests
for interface implementations through to the inner class so that its
capabilities are not lost.


5. Ability for versioning of interfaces to be inherent and dynamic
proxies be simple to create in order to provide backward
compatibility.

When an object is injected with an interface type (as all injected
types should be), then it becomes coupled to the version of the
interface that it was built against. If the injected interface
changes, then the target object may be broken. I'd love to be able to
create objects that adapt the old version of the interface to the new
version so that objects that rely on the old interface can still
work.

Sounds a bit crazy as the adapter object would need to reference the
interface symbol in two ways, both as the old version and the new
version. But it would rock.



So thanks for listening. I guess my overall idea is that if you are
dedicated to interface based design, then it would be great to make
available langauge features that support the design patterns that
become so important: factory, decorator, delegate, adaptor.

Cheers




Sam Pullara

unread,
Sep 26, 2009, 12:56:25 AM9/26/09
to no...@googlegroups.com
Lindsay,

This one was actually implemented in Java but no one used it because
it wasn't at the language level presumably. Not sure if you knew
about it:

http://www.j2ee.me/j2se/1.4.2/docs/api/java/beans/Beans.html

Sam

Alex Eagle

unread,
Sep 26, 2009, 12:50:23 PM9/26/09
to Noop
Hi Lindsay,

You've got the same mindset as we have, I think, and thanks for
explaining these ideas! We were planning #1 just as you describe it.
We are thinking of dealing with the diamond problem in multiple
delegation with something similar to #2. #3 - first-class events and
properties would be great, I'm not sure what our UI story will be
though. Maybe we'll want to be bytecode compatible with some other
properties impl like Scala or JavaFX. #4 is awesome and we should
write a proposal for that (or you could :). #5 scares me a lot from a
dependency management perspective - you'd need to keep the old version
of the code around? I guess webservices deal with the same problem,
and maybe OSGI could help, but still scary!

Sam: I had forgotten about that API, though it's funny that the
getInstanceOf method doc says: "This method is provided in Beans 1.0
as a hook to allow the addition of more flexible bean behaviour in the
future." Too bad Javabeans was such a weak substitute for properties!

-Alex

Lindsay Smith

unread,
Sep 26, 2009, 10:01:00 PM9/26/09
to Noop
Thanks for the reply, I'll write some kind of proposal for #4 if I get
inspired and have the time :).

#5 is indeed scary. The idea comes from my thinking about the roles
of interfaces in a system. There are two uses for interfaces in my
opinion, the first is the 'normal' kind, where all implementations of
an interface exist in the same code base as the interface definitions,
and the factory that provides the implementations has direct access to
the implementations. If you change the interface definition, you can
detect the implementations that are now invalid and update them.
These are 'internal' interfaces.

The second more difficult situation is where you allow other people to
provide implementations of an interface, and your system will
dynamically discover and make use of them. These 'external'
interfaces have to be treated differently as you need some dynamic way
to instantiate the object. E.g. in Java you might use a classname
string along with a classloader that can see the user-authored
classes. You can then instantiate the class via reflection. The next
step is determining if the object conforms to the interface that you
expect of it. This is where interface versioning becomes important
because if your internal interface has changed then objects written
before the change can no longer be used. Having an adaptor that
can make the old interface conform to the new one would be great. I
think that eclipse, with all its user component architecture,
explicitly adds the version number into the interface to manage
interface versioning.

I know that in Java there are classloader issues to deal with when it
comes to symbols matching up when your external class references a
public interface. So its a minefield, I've been thinking about how I
could do this myself using classloaders that inspect the classname of
a class being loaded and return something that conforms to the old
interface when appropriate, however I'm probably in for a whole lot of
trouble. Because in Java the idea of implementing an interface is
determined by the type hierarchy rather than just the capabilities of
the object, it may not be possible!

-Lindsay

Christian Edward Gruber

unread,
Sep 30, 2009, 12:23:58 PM9/30/09
to no...@googlegroups.com
As Alex said, this is pretty awesome, Lindsay.

As to #2, we weren't actually going to do it quite like that, but
rather we were going to have a disambiguation approach:

interface Bar {
void doStuff();
}

class Foo (delegate Bar bar, delegate Bar baz) {

}

This wouldn't compile, under our current thinking, because it's
ambiguous as to which delegate to delegate to. (I can't believe that
last bit of english is valid...)

Anyway, our current approach would do this:

class Foo (delegate Bar bar, delegate Bar baz) {
void doStuff() delegates to baz;
}

This is more important in cases of

interface Bar {
void doStuff();
void doBarStuff();
}
interface Baz {
void doStuff();
void doBazStuff();
}

where we doBarStuff() would obviously route to Bar, and doBazStuff()
to Baz, but the common signature is unclear. Currently, we force a
disambiguation as above. I think you're suggesting that the compiler
infer from the type, so we have less disambiguation to do. That's not
bad though, I sort of like the idea of a signature is a signature is a
signature, so if they share contract, you have to choose. I'm a
little worried about your approach creating more magic than the
programmer can process without tending to err, but maybe not. I'm
also somewhat polluted by my Objective-C background which cares more
about the method signature (in some senses) than the type. But this
isn't duck-typing, and it's a strongly typed language, so why not? I
have to mull this over.

As to #4, I was imagining something very much like an Objective-C
model, which has the "respondsTo" method, which simply asks if an
object can respond to a signature (Selector), with a companion
"invoke", so a call in noop if it adopted this sort of thing would
look like:

...
// @"foo" is a method selector, a signature primitive used for matching
if (myfoo.respondsTo(@"myMethod(Foo,Bar,Baz)")) {
myFoo.invoke(@"myMethod(Foo,Bar,Baz)",argz);
}

Selector being a first-class language element, the compiler would know
about it, and tools could properly do refactor operations on it, etc.

I haven't written this up as a proposal. Yours is similar, actually,
to another Objective-C construct which is overrding the invoke method,
to allow you to dispatch method calls how you will. I think among
these ideas is a sweet spot, but I haven't yet settled on it. I look
forward to your proposal on #4.

cheers,
Christian.

Reply all
Reply to author
Forward
0 new messages