• Post Reply Bookmark Topic Watch Topic
  • New Topic
programming forums Java Mobile Certification Databases Caching Books Engineering Micro Controllers OS Languages Paradigms IDEs Build Tools Frameworks Application Servers Open Source This Site Careers Other Pie Elite all forums
this forum made possible by our volunteer staff, including ...
Marshals:
  • Campbell Ritchie
  • Tim Cooke
  • paul wheaton
  • Jeanne Boyarsky
  • Ron McLeod
Sheriffs:
  • Paul Clapham
  • Liutauras Vilda
  • Devaka Cooray
Saloon Keepers:
  • Tim Holloway
  • Roland Mueller
Bartenders:

An interface for every class

 
Ranch Hand
Posts: 142
  • Mark post as helpful
  • send pies
    Number of slices to send:
    Optional 'thank-you' note:
  • Quote
  • Report post to moderator
I've just recently seen this recommended. I don't understand it. I've used interfaces for years but never one for every class, i.e. IPerson for Person.

The designer sais it offers protection. I responded that if the public signature must change, the interface will be MORE difficult to maintain.

I explained polymorphism, factories using a product analogy ect... He remains insistent that this is a good design.

Am I missing something here? This seems like a C header throw back to me.
 
(instanceof Sidekick)
Posts: 8791
  • Mark post as helpful
  • send pies
    Number of slices to send:
    Optional 'thank-you' note:
  • Quote
  • Report post to moderator
All generalizations are bad! Including that one of course.

Nah, interface per class sounds like overkill. Wait, as I think some more, dead wrong. Some interfaces will have many implementing classes that need not have any other interface of their own.

Robert Martin developed metrics for package abstraction and stability. The most stable and abstract packages make good use of interfaces, or maybe they're all interfaces. The most concrete classes don't need interfaces because they implement other interfaces defined in the stable packages. I have some hints on how this happens in my Dependency Inversion presentation, about here.

The OptimalJ product pages describe some of the dependency metrics. I wish I could find Martin's graph that shows an ideal line that packages should approach:

Hope that helps you (and the other guy!)
[ June 14, 2004: Message edited by: Stan James ]
 
Ranch Hand
Posts: 580
  • Mark post as helpful
  • send pies
    Number of slices to send:
    Optional 'thank-you' note:
  • Quote
  • Report post to moderator
I've seen that too and it is overkill imho. I would say only use interfaces where you need them (e.g. if you have more than one implementing class). One of the main advantages of OO software such as Java is that is easy to change. If at a later date you find you need an interface for a certain class, a quick refactor (maybe using a automated tool such as eclipse) and the jobs a good 'un.
D.
 
Ranch Hand
Posts: 374
  • Mark post as helpful
  • send pies
    Number of slices to send:
    Optional 'thank-you' note:
  • Quote
  • Report post to moderator
I've also heard (and disagreed with) this assertion. My contention is that, like any other design tool, interfaces have their place.

Interfaces are very good if you are trying to build a base framework with key extension points that will expect particular parameters. In short, structural libraries can and should make good use of interfaces.

On the other hand, if you are building a bottom-tier application that nobody will reuse, why on Earth would you design for someone to extend it? Don't waste time building interfaces, just build some solid, working code!
:roll:
 
author
Posts: 14112
  • Mark post as helpful
  • send pies
    Number of slices to send:
    Optional 'thank-you' note:
  • Quote
  • Report post to moderator

Originally posted by David Hibbs:
Don't waste time building interfaces, just build some solid, working code!



Of course building working code more or less requires unit testing it, which requires testing units in isolation, which often enough requires to inject dummy- or mock-implementations into the class under test - which requires the class to be implemented against an interface...

So I often find that *many* of my classes have a associated interfaces.

Just writing an interface for *every* class "because you have to do it" is just plain silly, on the other hand...
 
Ranch Hand
Posts: 5093
  • Mark post as helpful
  • send pies
    Number of slices to send:
    Optional 'thank-you' note:
  • Quote
  • Report post to moderator
Having a distinct interface for each class is as wrong as having a different factory for every class...
And yes I've encountered it.
For every class there was a factory, including for many of the factories themselves (so there would be a GreenDoohicky, a YellowDoohicky, a DooHicky, a GreenDoohickyFactory, a YellowDoohickyFactory, and a GreenDoohickyFactoryFactory (but no DoohickyFactory of course because Doohicky is abstract) and a YellowDoohickyFactoryFactory).

The constructors of the Doohickies were protected and their factories were declared as friends (this was a C++ project) so they were the only way to generate instances.

That same project had taken MVC to the next level by implementing an MVC pattern inside each of the Model, View and Controller layers of the outer MVC pattern. In total there were some 12 layers to go through between database and screen or printer.
Of course the interface objects between the layers had all to be constructed using factories and passed to the other layer wrapped in other objects obtained from that layer which would also require factories to create.

Suffice to say all that object creation led to an application that was a performance nightmare but the architect could proudly proclaim he'd created the perfectly decoupled application.
 
Ilja Preuss
author
Posts: 14112
  • Mark post as helpful
  • send pies
    Number of slices to send:
    Optional 'thank-you' note:
  • Quote
  • Report post to moderator
An important thing to notice is that interfaces actually more closely belong to the clients than to the classes which implement them - they define what methods a client is working on.

Google for the Dependency Inversion Principle.
 
Ranch Hand
Posts: 268
  • Mark post as helpful
  • send pies
    Number of slices to send:
    Optional 'thank-you' note:
  • Quote
  • Report post to moderator
I use interfaces to abstract away the "essential" behavior of a thing. What do I mean by "essential"? Well, when I decide to write a Dog class, for instance, there's lots of things that I can chuck in there...dogs scratch, dig, bark, beg, roll over, etc. Which of these things am I interested in representing in my particular application? For the purposes of my app, I decide which of these features are salient, and then even more, which of them are *defining behaviors*. If a defining behavior is removed, and the thing that's left would no longer be considered a "dog" for the purposes of my app, then it's a defining, or essential, behavior.

I consider if this is likely to remain so over many, many versions of the application, and all possible future uses I can think of, and I even try to consider those I cannot yet possibly fathom. If the behavior is just so essential to the class that it would irrevocably change the nature of the beast if it were removed, then it survives as an essential behavior.

These kinds of behaviors are worth abstracting into interfaces. It is notable to consider that there are and will always be whole classes, indeed whole packages, that have no such defining behaviors and these should be treated as unstable (to use Fowler's very apt terminology), as they will likely change from version to version. But the behaviors that define the nature of the application and its basic purpose should be encapsulated in interfaces, and these interfaces should be set off into a package structure that will remain stable over many versions. This serves as a sort of basic bedrock from which the current incarnation with all its version-specific googahs can be built. This is sort of like an application "framework" (using the word in a slightly different sense from its usual usage). The bottom line: these are meant to be the long-lived APIs that form the basic functionality of your app. If you find you must change them down the road at some point, it's nothing less than an admission that you misunderstood your business in a fundamental way at the time they were designed. (It is common to see all of the "obvious" functionality that it would simply never make sense to change go in here, and it's even more common to see the amount of code in these packages be very, very small compared to the rest of the codebase--though these APIs typically require much of the time and thought that goes into a project.)

I use interfaces in another way as well that's fundamentally different from this, as a language construct for enforcing contracts, which can be very useful even for a specific version, non-essential kind of behavior (for instance, you might have a listener interface, the purpose of which completely pertains to some very unstable feature of your app). These interfaces would be bundled in packages alongside implementation classes and, more or less, treated as if they themselves were implementation with the proviso that they are, even so, abstractions to some degree. Even these interfaces should be established with the idea in mind that they should be stable at least throughout the development cycle for that particular version (in other words, the "essential" behaviors for that particular version's feature the interface supports should be distilled into that interface and not change). It's often useful along this vein to split off a package that keeps these kinds of "somewhat stable" abstractions separate from detailed implementation. By building up level upon level, you can isolate ripple due to change to the levels that the change actually addresses.

So, the point is, the language construct that is the interface should be used to crystallize aspects of your design or enforce contracts or some other well-defined purpose. To simply say, well, let's go ahead and use it everywhere is just kind of silly if its usage is not supporting some aspect of the design or addressing some aspect of the restrictions under which the code should evolve as time goes on.

sev
[ June 21, 2004: Message edited by: sever oon ]
 
On top of spaghetti all covered in cheese, there was this tiny ad:
Smokeless wood heat with a rocket mass heater
https://woodheat.net
reply
    Bookmark Topic Watch Topic
  • New Topic