Style and practice question: use of interfaces

R

Richard C. Cobbe

Greetings, all.

I have a question for the Java programming community at large.

For years, the software engineering curriculum has been telling us to
program to interfaces, rather than to implementations, and the benefits of
this involve reasons we've all heard before: encapsulation, low coupling,
better maintainability, and so forth. This is a widespread,
non-controversial point, and I'd guess that anybody who's had even a little
formal training in programming has heard this before.

With Java, programmers can actually use the language's interface
construction to separate the interface from the implementation and actually
realize the style described above. But that doesn't seem to be what's
happening -- some colleagues and I have looked at various Java projects and
found that people don't actually do this.

So, why the disconnect between theory and practice? What practical issues
come up to encourage people to program to classes?

I'd love to hear your thoughts on this.

Thanks much,

Richard
 
J

jan V

So, why the disconnect between theory and practice? What practical issues
come up to encourage people to program to classes?

I'd love to hear your thoughts on this.

I recently worked for a company with a very odd take on the Java interfaces
thing. In a complex library consisting of 500+ heavily inter-dependent
types, more than a third of those were interfaces. As someone with many
years of Java experience (nearly 10) I had never seen such a high
interface/classes ratio. A ratio of 1:20 feels "normal", 1:10 would feel
"high", but 1:3 felt wrong from day one (for me).

As I got to learn this company's library, and started to work on code which
used the library, I was horrified to see that this company's own "engineers"
almost invariably did NOT code to the interfaces, but to the concrete
classes instead.

It transpired that writing an interface, but not actually using it (the way
it's mean to be used), is part of that company's "culture". Go figure...
 
S

Stefan Ram

I'd love to hear your thoughts on this.

I did so recently, when I was working on a Java implementation
of state monads.

I wanted to defined the "bind" operation for a state monad.

First, I used interfaces to define what a state, value,
product-and-state-pair, operation and parameterized operation
is:

interface StateType {};

interface ValueType {};

interface ProductAndState<ValueType,StateType>
{ ValueType getProduct();
StateType getState(); }

interface Operation<ValueType,StateType>
{ ProductAndState<ValueType,StateType> execute( StateType state ); }

interface ParameterizedOperation<ValueType,StateType,ParameterType>
{ Operation<ValueType,StateType> asDeterminedBy( final ParameterType parameter ); }

Now, I can define the bind-operation using only these interfaces:

class Bind<ValueType,StateType,ProductType>
{ Operation<ValueType,StateType> firstOperation;
ParameterizedOperation<ProductType,StateType,ValueType> secondOperation;
Bind
( final Operation<ValueType,StateType> firstOperation,
final ParameterizedOperation<ProductType,StateType,ValueType> secondOperation )
{ this.firstOperation = firstOperation;
this.secondOperation = secondOperation; }
Operation<ProductType,StateType> composition()
{ return new Operation<ProductType,StateType>()
{ public ProductAndState<ProductType,StateType> execute( final StateType initialState )
{ ProductAndState<ValueType,StateType> intermediateProductAndState =
firstOperation.execute( initialState );
return secondOperation.asDeterminedBy( intermediateProductAndState.getProduct() )
.execute( intermediateProductAndState.getState() ); }}; }}

Finally, I can implement the interfaces and use the bind operation
on the implementations:

class MemoryState implements StateType
{ MemoryState( final int value ){ this.value = value; }
int value;
public int getValue(){ return this.value; }}

class IntValue implements ValueType
{ IntValue( final int value ){ this.value = value; }
public int asInt(){ return this.value; }
int value; }

class IntProductAndMemoryState implements ProductAndState<IntValue,MemoryState>
{ final IntValue product;
final MemoryState state;
IntProductAndMemoryState( final IntValue product, final MemoryState state )
{ this.product = product; this.state = state; }
public IntValue getProduct(){ return product; }
public MemoryState getState(){ return state; }}

class IntValueOperation implements Operation<IntValue,MemoryState>
{ final IntValue value;
IntValueOperation( final IntValue value ){ this.value = value; }
public ProductAndState<IntValue,MemoryState>
execute( final MemoryState state )
{ return new IntProductAndMemoryState( value, state ); }}

class ReaderOperation implements Operation<IntValue,MemoryState>
{ ReaderOperation(){}
public ProductAndState<IntValue,MemoryState>
execute( final MemoryState state )
{ return new IntProductAndMemoryState
( new IntValue( state.getValue() ), state ); }}

class WriterOperation implements Operation<IntValue,MemoryState>
{ IntValue value; WriterOperation( final IntValue value )
{ this.value = value; }
public ProductAndState<IntValue,MemoryState>
execute( final MemoryState state )
{ return new IntProductAndMemoryState
(( IntValue )null, new MemoryState( value.asInt() )); }}

class ReadValue
implements ParameterizedOperation<IntValue,MemoryState,IntValue>
{ public Operation<IntValue,MemoryState> asDeterminedBy( IntValue value )
{ return new ReaderOperation(); /* ignores the value */ }}

class WriteValue
implements ParameterizedOperation<IntValue,MemoryState,IntValue>
{ public Operation<IntValue,MemoryState> asDeterminedBy( IntValue value )
{ return new WriterOperation( value ); /* writes the value */ }}

class Monade
{
static Operation<IntValue,MemoryState> bind
( final Operation<IntValue,MemoryState> first,
final ParameterizedOperation<IntValue,MemoryState,IntValue> second )
{ return new Bind<IntValue,MemoryState,IntValue>( first, second ).composition(); }
static Operation<IntValue,MemoryState> value( final int i )
{ return new IntValueOperation( new IntValue( i )); }

static ParameterizedOperation<IntValue,MemoryState,IntValue> writeValue()
{ return new WriteValue(); }
static ParameterizedOperation<IntValue,MemoryState,IntValue> readValue()
{ return new ReadValue(); }

public static void main( final String[] _ )
{ final MemoryState initState = new MemoryState( 0 );
final int initValue = 2;
ProductAndState<IntValue,MemoryState> productAndState =
bind( bind( value( initValue ), writeValue() ), readValue() ).
execute( initState );
java.lang.System.out.println( productAndState.getProduct().asInt() ); }}

So, this technique would be:

- first, define the types (interfaces)
- then, define all algorithms on these types (interfaces)
- finally, define "thin" implementations using the types and
algorithms defined in the previous steps

However, the same result can be achieved using refactoring by
factoring out algorithms and interfaces from a thick
implementation.

(An additional nice idea would be to use a multimethod
framework for the algorithms. So that the implementations
might use a multi-argument run-time dispatch in cases,
when this is helpful.)
 
T

Thomas Hawtin

Richard said:
For years, the software engineering curriculum has been telling us to
program to interfaces, rather than to implementations, and the benefits of
this involve reasons we've all heard before: encapsulation, low coupling,
better maintainability, and so forth. This is a widespread,
non-controversial point, and I'd guess that anybody who's had even a little
formal training in programming has heard this before.

With Java, programmers can actually use the language's interface
construction to separate the interface from the implementation and actually
realize the style described above. But that doesn't seem to be what's
happening -- some colleagues and I have looked at various Java projects and
found that people don't actually do this.

I think there is a widespread misunderstanding between interface the
general concept and Java interface types.

Every Java class has an interface. It just so happens to be conveniently
bundled with the code for easy construction and maintenance.

Don't confuse Java interfaces with C header files. They do completely
different things. In fact I believe Java kicked off with the idea of
getting rid of header files.

"Programming to the interface" is no more or less hard if it's to a the
interface of an interface or an interface of a class. You can make
assumptions about the implementation either way. (Although a class has
more ways to expose its implementation. The easy solution to that is
don't write you classes badly.)

I once worked for a company where the core of the new product had been
written such that pretty much every class had an associated interface.
Trying to deal with the code base drove programmers to distraction.
Apart for the bloke who designed it that way. He wouldn't be my first
choice employee.

Tom Hawtin
 
R

Roedy Green

With Java, programmers can actually use the language's interface
construction to separate the interface from the implementation and actually
realize the style described above. But that doesn't seem to be what's
happening -- some colleagues and I have looked at various Java projects and
found that people don't actually do this.

What ARE they doing?

--
Bush crime family lost/embezzled $3 trillion from Pentagon.
Complicit Bush-friendly media keeps mum. Rumsfeld confesses on video.
http://www.infowars.com/articles/us/mckinney_grills_rumsfeld.htm

Canadian Mind Products, Roedy Green.
See http://mindprod.com/iraq.html photos of Bush's war crimes
 
R

Roedy Green

As I got to learn this company's library, and started to work on code which
used the library, I was horrified to see that this company's own "engineers"
almost invariably did NOT code to the interfaces, but to the concrete
classes instead.

The theory is classes are for insiders, interfaces are hooks for
outsiders. Sound like they are not properly hooking up their
interfaces though.

--
Bush crime family lost/embezzled $3 trillion from Pentagon.
Complicit Bush-friendly media keeps mum. Rumsfeld confesses on video.
http://www.infowars.com/articles/us/mckinney_grills_rumsfeld.htm

Canadian Mind Products, Roedy Green.
See http://mindprod.com/iraq.html photos of Bush's war crimes
 
R

Roedy Green

"Programming to the interface" is no more or less hard if it's to a the
interface of an interface or an interface of a class. You can make
assumptions about the implementation either way. (Although a class has
more ways to expose its implementation. The easy solution to that is
don't write you classes badly.)

The idea of an interface is that is exposes a bare minimum
functionality to get the job done. A class spills out everything.

An interface makes it easier to plug in a replacement. There are
fewer glue points and less temptation to build more spider webs that
necessary.

So you might have several interfaces on the same class, depending what
role it is playing.

I primarily think of interfaces as places where I want to plug in
different code or might want to in future. The classic example is a
set of dynamic classes all of which implement a common interface.
Think of the JCE or JDBC driver scheme where vendors can plug their
implementations into the official Java system.


--
Bush crime family lost/embezzled $3 trillion from Pentagon.
Complicit Bush-friendly media keeps mum. Rumsfeld confesses on video.
http://www.infowars.com/articles/us/mckinney_grills_rumsfeld.htm

Canadian Mind Products, Roedy Green.
See http://mindprod.com/iraq.html photos of Bush's war crimes
 
H

HK

Richard said:
With Java, programmers can actually use the language's interface
construction to separate the interface from the implementation and actually
realize the style described above. But that doesn't seem to be what's
happening -- some colleagues and I have looked at various Java projects and
found that people don't actually do this.

You mean people use

HashMap bla = new HashMap();
ArrayList urx = new ArrayList();
public void doThings(HashSet oompf) { ... }

instead of

Map bla = new HashMap();
List urx = new ArrayList();
public void doThings(Set oompf) { ... }

Well, it took me some time to get used to the latter.
I guess it is a matter of experience and a lack of
formal help from the compiler.

Harald.
 
R

Richard C. Cobbe

Roedy Green said:
What ARE they doing?

Pretty much just using the classes directly, and ignoring the frequent
disconnect between a class's intended interface and its actual one.

Richard
 
R

Richard C. Cobbe

HK said:
You mean people use

HashMap bla = new HashMap();
ArrayList urx = new ArrayList();
public void doThings(HashSet oompf) { ... }

instead of

Map bla = new HashMap();
List urx = new ArrayList();
public void doThings(Set oompf) { ... }

That's pretty much what we've seen, yes.
Well, it took me some time to get used to the latter.
I guess it is a matter of experience and a lack of
formal help from the compiler.

I'm also interested in how you work with the classes that you yourself
write. Our experience is that most people tend not to define interfaces
for them and simply use the class names directly, as in your first example
above.

Richard
 
R

Richard C. Cobbe

I think there is a widespread misunderstanding between interface the
general concept and Java interface types.

Every Java class has an interface. It just so happens to be
conveniently bundled with the code for easy construction and
maintenance.

Don't confuse Java interfaces with C header files. They do completely
different things. In fact I believe Java kicked off with the idea of
getting rid of header files.

"Programming to the interface" is no more or less hard if it's to a
the interface of an interface or an interface of a class. You can make
assumptions about the implementation either way. (Although a class has
more ways to expose its implementation. The easy solution to that is
don't write you classes badly.)

So would you say that Java's interfaces don't provide any greater
separation between a component's interface and its implementation? Is that
a fair summary?
I once worked for a company where the core of the new product had been
written such that pretty much every class had an associated
interface. Trying to deal with the code base drove programmers to
distraction. Apart for the bloke who designed it that way. He wouldn't be
my first choice employee.

That is interesting. Why did the code base drive programmers to
distraction? And why wouldn't the original designer be your first-choice
employee?

I'm not disputing either of these opinions, by the way. I'm just trying to
understand the observed disconnect between what software engineers
recommend as good design practice, and what developers actually do.

Thanks much,

Richard
 
H

HK

Richard said:
I'm also interested in how you work with the classes that you yourself
write. Our experience is that most people tend not to define interfaces
for them and simply use the class names directly, as in your first example
above.

Things to be manipulated tend to get an
interface defined first. I think along
the lines of: to manipulate this thing
properly, what is the minimum functionality
I need to do that.

Also if I immediately foresee several
possible implementations serving slightly
different speed/space tradeoffs, I go
for an interface.

If, however, I just want to get some work
done, I don't define and interface first.

See http://www.ebi.ac.uk/~kirsch/monq-doc/
yourself to see if I got it right.-)

Harald.
 
I

Ingo R. Homann

Hi,
Also if I immediately foresee several
possible implementations serving slightly
different speed/space tradeoffs, I go
for an interface.

I think, that is the important thing about it!

IMHO, it does not make sense to declare an interface for *every* class
(that probably includes all public methods of the class)!

By the way, this is also the way, sun goes (*): There are interfaces for
the different collection-classes, for exmaple, but not every class sun
provides has an own interface...

Ciao,
Ingo

(*) which does not mean that this is the best way ;-)
 
T

Thomas Hawtin

Richard said:
So would you say that Java's interfaces don't provide any greater
separation between a component's interface and its implementation? Is that
a fair summary?

If there is only one implementation then Java interfaces don't buy you
anything. Client code that doesn't new and otherwise programs to the
class interface wouldn't notice if you swapped the class out for a Java
interface of the same name. When you use new you are specifying, and
hence at that point programming to, the implementation. Similarly you
can replace a Java interface with a class.

There are technical aspects of compatibility, but these do not effect
the general notion of interface.
That is interesting. Why did the code base drive programmers to
distraction? And why wouldn't the original designer be your first-choice
employee?

Two reasons.

If you are reading the implementation, the documentation is in a
different file. The result, other than wasting lots of time and breaking
concentration, is out of sync JavaDocs.

Trying to follow a path of execution is difficult. Use your editor to
jump to the source of a called method and you end up in the interface.
Then you have to jump out and manually find the correct file with the
implementation.

There's also the fun of having two different type names for exactly the
same concept with only a technicality between them.

Tom Hawtin
 
?

.

Greetings, all.

I have a question for the Java programming community at large.

For years, the software engineering curriculum has been telling us to
program to interfaces, rather than to implementations, and the benefits of
this involve reasons we've all heard before: encapsulation, low coupling,
better maintainability, and so forth. This is a widespread,
non-controversial point, and I'd guess that anybody who's had even a little
formal training in programming has heard this before.

Are you sure you can make this assumption? It has been my experience that
some programmers have gaps in their knowledge. Maybe they pre-date
widespread acceptance of OOP and haven't been keeping current. I've had
people nod their head knowingly during a team meeting and then later ask
me what everyone was talking about.

So, not having the proper formal training is one possibility.
With Java, programmers can actually use the language's interface
construction to separate the interface from the implementation and actually
realize the style described above. But that doesn't seem to be what's
happening -- some colleagues and I have looked at various Java projects and
found that people don't actually do this.

So, why the disconnect between theory and practice? What practical issues
come up to encourage people to program to classes?

I'd love to hear your thoughts on this.

School and company environments are much different. I have seen
programmers make decision on how to code something because it was faster
or because they were coding faster than they were thinking. I've seen
comments in code that say things like:

// TODO: in a hurry, have to come back and do this properly

I'd check source control and find they check this in two years ago. They
have been promoted and now someone else is responsible for the code base.
The new person isn't sure what "properly" means. Additionally, management
puts pressure on the programmers to not change anything it is not broken.

I've not stopped to see if this is common. I tend to see it is common at
certain companies I have worked for. I've seen a co-op question the team
on how they are programming and start a refactor of the code base; a few
years later we hired that same co-op as full-time and now he is
programming just as bad as the team before the refactoring (and the team
has reverted to their bad habits). This was obviously a cultural thing and
I strongly believe it was driven by management decisions.

Finally, I have seen programmers how know little or nothing about Java or
OOP (they are usually C programmers who switched to C++ when their IDE
switched from C to C++) and they start doing Java programming. Management
tells them to buy some books (applied programming books or cookbook type
books; none of this "theoretical cr*p") and learn it because it is the
next big thing or they want to leverage something from the Java community.

These programmers are really more hackers. They learn by trial and error.
They usually don't know there is a better way if what they do seems to
work for them.

Summary: look to see if the programmers you examine are:

1) Really just faking it and don't know how to properly use interfaces.
2) Under some cultural influence (pressure/stress) that makes they program
in ways they normally would not.
3) Really just hackers
 
J

jan V

I'm not disputing either of these opinions, by the way. I'm just trying
to
understand the observed disconnect between what software engineers
recommend as good design practice, and what developers actually do.

A developer isn't a software engineer, and a software engineer isn't a
developer.

For me, developer is synonymous with "programmer". Programmer/Developer is
the seed that may turn into a software engineer, after many, many years of
experience, and... crucially... after the programmer has ditched the
"straight to code" mindset virtually all beginners have (how many beginners'
textbooks do you know which do requirements gathering, analysis, design
etc.. *before* diving into code?).

Software engineers have a perfect understanding of why interfaces were
included in Java's design, and software engineers will use Java interfaces
the way they were intended to be used.

Many developers don't understand so many "bigger picture" things (i.e.
typical *software engineering* issues) that it is no wonder there is an
observed disconnect.... we very clearly have a multitude of observed
disconnects spanning the whole software engineering spectrum. Simply because
too many people creating software systems are developers, not software
engineers.
 
T

Thomas Hawtin

Roedy said:
The idea of an interface is that is exposes a bare minimum
functionality to get the job done. A class spills out everything.

A class *can* spill out everything. It doesn't have to. If the class is
only exposing public methods (plus constants, perhaps) and you are using
the same mechanism to obtain an instance as you did with the class, then
it matters not what is class and what is Java interface.

If a programmer can't program to an interface, then he or she isn't
going to be able to write a good class interface or Java interface
interface anyway.
So you might have several interfaces on the same class, depending what
role it is playing.

If you don't have different implementations, which is the usual case,
then why introduce a Java interface? And if you do have have multiple
implementations, why not just use that abstract class? If you need
further implementations that don't use the abstract class, then you only
need to change the other implementations, not the client code.
I primarily think of interfaces as places where I want to plug in
different code or might want to in future. The classic example is a
set of dynamic classes all of which implement a common interface.
Think of the JCE or JDBC driver scheme where vendors can plug their
implementations into the official Java system.

This is where things become inverted. Essentially the client code is
that of the drivers. IMO, JDBC would be better off with an API/SPI
system rather than a system of AbstractMethodErrors.


It's as easy to program to the interface of static methods as it is to
the interface of a Java interface.

Tom Hawtin
 
I

iamfractal

Thomas Hawtin skrev:


Clip.
If you don't have different implementations, which is the usual case,
then why introduce a Java interface?

Agreed. Interfaces are solely for variance encapsulation.


And if you do have have multiple
implementations, why not just use that abstract class?

Because this can sometimes demand that a class inherit from more than
one abstract class.

..ed
 
R

Richard C. Cobbe

Greetings, all.

I have a question for the Java programming community at large.

So, why the disconnect between theory and practice? What practical issues
come up to encourage people to program to classes?

Thanks to everyone for all the responses. I think everyone's comments can
be distilled into two points:

First, most people believe that interfaces are useful primarily when the
programmer expects to have multiple implemetations of the interface, as is
the case with many of the collection classes in java.util.

Second, the general consensus is that Java interfaces don't provide any
mechanisms to separate interface and implementation that aren't already in
Java's class and package systems. (This one seems to be less of an issue
than the first point above.)

I'm a little surprised that only one person brought up the added effort of
keeping the interfaces and classes in sync. Do people in general feel that
this isn't much of an issue? Have tools like Eclipse largely removed the
drudgery from that task?

I'd also like to revisit the first point above. It appears that many
programmers are in the habit of using java.util.Map instead of, say,
java.util.HashMap. Does this extend beyond the use of the collection
classes? In particular, if a programmer feels that he or she will have
multiple implementations of a single interface, does he or she typically
write down that interface explicitly? This situation comes up more often
than just data structure design; the Composite pattern is based on the idea
of multiple implementations of a particular interface.

Richard
 
M

Monique Y. Mudama

I'd also like to revisit the first point above. It appears that
many programmers are in the habit of using java.util.Map instead of,
say, java.util.HashMap.

Doesn't this only help/work if the interface completely describes all
the methods you need? Or are implementations that contain more
methods than the interface considered to be bad design?

I definitely use Foo instead of SpecialFoo when any Foo would work,
but it's not uncommon to find that no, I really do need SpecialFoo.
Is this a sign that Foo wasn't well-conceived in the first place, or
simply a normal fact of life?
 

Ask a Question

Want to reply to this thread or ask your own question?

You'll need to choose a username for the site, which only take a couple of moments. After that, you can post your question and our members will help you out.

Ask a Question

Members online

No members online now.

Forum statistics

Threads
473,995
Messages
2,570,230
Members
46,819
Latest member
masterdaster

Latest Threads

Top