the trend for putting interfaces everywhere

171 views
Skip to first unread message

philip schwarz

unread,
Sep 5, 2010, 4:12:25 PM9/5/10
to Growing Object-Oriented Software
Hi all,

in Reused Abstractions Principle (RAP) http://parlezuml.com/blog/?postid=934
, Jason Gorman says

###################################################################################################################
I introduced this principle 10 years ago when discussing OO design to
counter the trend for speculative abstractions in many of the projects
I encountered. Most particularly, the trend for putting interfaces
everywhere, regardless of whether that interface represented some
commonality betweren two or more types of object - which is what
they're really for. So I will stress that "programming to interfaces"
is not good OO design, any more than "don't use getters and setters"
is. These are overly simplistic formulas that mask more fundamental
and nuanced principles. If the only class that ever implements the
Customer interface is CustomerImpl, you don't really have polymorphism
and substitutability because there is nothing in practice to
substitute at runtime. It's fake generality. All you have is
indirection and code clutter, which just makes the code harder to
understand.
###################################################################################################################

Experienced and skilled as he is, I am certain he doesn't mean that an
interface is not justified if there is only one implementation, but I
wonder if he would view Nat and Steve's following practices as a
manifestation of "the trend for putting interfaces everywhere":

###################################################################################################################

"Identifying Relationships with Interfaces (GOOS p63): We use Java
interfaces more liberally than some other developers. This reflects
our emphasis on the relationships between objects, as defined by their
communication protocols. We use interfaces to name the roles that
objects can play and to describe the messages they’ll accept."

"Budding Off: Defining a New Service That an Object Needs and Adding a
New Object to Provide It (GOOS p61) When the code is more stable and
has some degree of structure, we often discover new types by “pulling”
them into existence. We might be adding behavior to an object and find
that, following our design principles, some new feature doesn’t belong
inside it. Our response is to create an interface to define the
service that the object needs from the object’s point of view. We
write tests for the new behavior as if the service already exists,
using mock objects to help describe the relationship between the
target object and its new collaborator; ...The development cycle goes
like this. When implementing an object, we discover that it needs a
service to be provided by another object. We give the new service a
name and mock it out in the client object’s unit tests, to clarify the
relationship between the two. Then we write an object to provide that
service and, in doing so, discover what services that object needs. We
follow this chain (or perhaps a directed graph) of collaborator
relationships until we connect up to existing objects, either our own
or from a third-party API. ...We think of this as “on-demand” design:
we “pull” interfaces and their implementations into existence from the
needs of the client, rather than “pushing” out the features that we
think a class should provide.

###################################################################################################################

Philip

Steve Freeman

unread,
Sep 5, 2010, 5:21:45 PM9/5/10
to growing-object-o...@googlegroups.com
This is an endless topic of dissension (and one reason I have a problem with partial mocking).

It's true that many uses of interfaces are simply adding a skin to a concrete class. There's no real sense of an object playing one or more roles. 'Customer' is a nice example, because it sounds too general to describe a role. A Customer class that implements, say, Purchaser, might be more appropriate.

It's about expressing relationships in the code, and trying to make dependencies as narrow as possible.

S.

Steve Freeman

Winner of the Agile Alliance Gordon Pask award 2006
Book: http://www.growing-object-oriented-software.com

+44 (0) 797 179 4105
M3P Limited. http://www.m3p.co.uk
Registered office. 2 Church Street, Burnham, Bucks, SL1 7HZ.
Company registered in England & Wales. Number 03689627

James Carr

unread,
Sep 5, 2010, 6:05:19 PM9/5/10
to growing-object-o...@googlegroups.com
Yes, this topic is always hotly debated on teams I am on. Another
commonality I see on various teams in the industry is having
***Service interfaces with ***ServiceImpl concrete implementations.
Not adhering to these kinds of conventions often get me "in trouble".
Sometimes I debate it, sometimes I accept the team standard until I
can convince otherwise. :)

Thanks,
James

Steve Freeman

unread,
Sep 5, 2010, 6:09:12 PM9/5/10
to growing-object-o...@googlegroups.com
I'm not sure if it's in the book, but to me XXX, XXXImpl (or, worse, IXXX, XXX), is a missed opportunity. I want my class name to tell me /something/ about the implementation so I don't have to look in the code: even if it's just that the implementation is backed by a hash set.

S.

philip schwarz

unread,
Sep 5, 2010, 6:30:53 PM9/5/10
to Growing Object-Oriented Software
Yes, it is in the book, you elaborate on precisely those thoughts in
the section called "Impl Classes Are Meaningless", on p63.

Philip

Ben Butler-Cole

unread,
Sep 6, 2010, 4:08:32 AM9/6/10
to growing-object-o...@googlegroups.com
Gorman seems to be suggesting that an interface is only worthwhile if there is more than one implementation. While his general thrust (that a one-to-one relationship between interfaces and implementations indicates "fake generality") may be valid, there is a perfectly good case that he doesn't seem to consider -- a single class implementing multiple interfaces (each of which defines its relationship with a different set of clients).

-Ben

J. B. Rainsberger

unread,
Sep 6, 2010, 8:54:36 AM9/6/10
to growing-object-o...@googlegroups.com
On Sun, Sep 5, 2010 at 17:12, philip schwarz
<philip.joh...@googlemail.com> wrote:
> So I will stress that "programming to interfaces"
> is not good OO design, any more than "don't use getters and setters"
> is. These are overly simplistic formulas that mask more fundamental
> and nuanced principles.

They are Novice principles. I appreciate Jason's perspective, and I
think I understand it, but when I teach novices, I need to give them
rules to follow. I give them these rules to help lead them towards
learning the "more fundamental and nuanced principles". I hope Jason
remembers what it felt like to learn modular design principles for the
first time.

> If the only class that ever implements the
> Customer interface is CustomerImpl, you don't really have polymorphism
> and substitutability because there is nothing in practice to
> substitute at runtime. It's fake generality. All you have is
> indirection and code clutter, which just makes the code harder to
> understand.

Jason appears not to have mastered the difference between "I don't
like it" and "It's bad".
--
J. B. (Joe) Rainsberger :: http://www.jbrains.ca ::
http://blog.thecodewhisperer.com
Diaspar Software Services :: http://www.diasparsoftware.com
Author, JUnit Recipes
2005 Gordon Pask Award for contribution to Agile practice :: Agile
2010: Learn. Practice. Explore.

David Peterson

unread,
Sep 6, 2010, 10:40:58 AM9/6/10
to growing-object-o...@googlegroups.com
I mentioned the discussion to Jason. I don't think he's joining the group, but he said he was happy for me to post his response (below).

I won't publish his e-mail address because it's bad form, but let me know if any of you are interested in the S.O.L.I.D. event at Bletchley or running a session at SC2010 and I'll put you in touch with him.

---

I'm not a member of that group, but I'm well aware of the GOOS guys and have a great deal of respect for them and their point of view.
 
Undoubtedly, there are "schools" of OO design, and we don't all agree on everything. You cannot invalidate either side of the argument by saying "yeah, but that's just your opinion", since it's actually just opinion on both sides. Indeed, most OO design principles have not been objectively tested, as far as I'm aware. They're products of instinct built on years of subjective experience. What the GOOS guys do works for them. Hoorah! What I do works for me. Double hoorah!
 
What I can say with confidence is that religiously following simplistic formulas almost always leads to trouble. There may be novice OO designers, but I'm not sure there's such a thing as "novice OO design", any more than we can turn a fiendishly difficult ski slope into a "novice ski slope" just by telling people "try to stick to the left" before we send them hurtling down.
 
I spend a great deal of my time working with OO newbies, and I've never found a need to give them potted answers. "Tell, Don't Ask", for example, is really very straightforward. Try to put the behaviour where the data is and favour fewer, higher-level interactions between objects. Then you show them some examples and maybe ask them to refactor some code that's very data-centric to achieve those goals. If I boiled that down to "don't use getters and setters" I'm not only risking missing the whole point, but I'm potentially insulting the intelligence of people who may be new to OO design but are probably smarter than I am. It's not rocket science, after all. The ultimate arbiter of what works and what doesn't is the quality of the end result. If your classes are more cohesive and loosely coupled, then you have succeeded, regardless of what formula you were following. It's perfectly possible to riddle your code with low-level dependencies and still not use getters and setters. I've seen it with my very own mince pies!

If anyone wants to see how I teach "novices" OO design, then they can come along to Rock S.O.L.I.D. at Bletchley park on Sept 16th - it's in a good cause. And a good way to progress this discussion might be for someone to run a session on it at SC2010. It's always more meaningful l when we get around some real code, I'm finding :)

Cheers
 
J

J. B. Rainsberger

unread,
Sep 6, 2010, 5:53:15 PM9/6/10
to growing-object-o...@googlegroups.com
On Mon, Sep 6, 2010 at 11:40, David Peterson <pete...@gmail.com> wrote:

> "What I can say with confidence is that religiously following…"

…and I'm out of the discussion.

philip schwarz

unread,
Sep 6, 2010, 6:16:09 PM9/6/10
to Growing Object-Oriented Software
When I read Jason Gorman's post, I wanted to comment, but commenting
was disabled, so I opened this thread and immediately tweeted him the
following:

is "Identifying Relationships with Interfaces" a case of "the
trend for putting interfaces everywhere"? <link to this thread>

to which he kindly replied to as follows:

Possibly. Depends on why you're doing it. There's an obvious
tension between RAP, SRP and Interface Segregation

In addition to his fuller response posted above by David Peterson, he
has now enabled comments on his site, and written a full blog post:

Ah, But What About Interface Segregation?" I Hear you Cry -
http://parlezuml.com/blog/?postid=935

Jason Gorman, if you happen to read this: thank you for your time/
patience.

Philip

Nat Pryce

unread,
Sep 12, 2010, 3:28:23 PM9/12/10
to growing-object-o...@googlegroups.com
A very brief addition to this thread: a Mock Object *is* another
implementation of the interface. Ok, it's for testing not production
code. But that doesn't make the need of its existence any less valid.
Tests are as much part of the system as the code that runs in the
deployed system (and in many systems, some of the tests *are* included
in with and run in the deployed system).

--Nat

On 5 September 2010 21:12, philip schwarz

--
http://www.natpryce.com

Lance Walton

unread,
Sep 12, 2010, 4:09:32 PM9/12/10
to growing-object-o...@googlegroups.com
I actually don't buy the 'if it's only got one implementation, the interface is redundant' argument any more than the 'if a method is only called from one place it should be inlined' argument. Both give a name to an abstraction and that has enough value for me.

Regards,

Lance

J. B. Rainsberger

unread,
Sep 12, 2010, 5:20:40 PM9/12/10
to growing-object-o...@googlegroups.com
On Sun, Sep 12, 2010 at 16:28, Nat Pryce <nat....@gmail.com> wrote:

> A very brief addition to this thread: a Mock Object *is* another
> implementation of the interface.  Ok, it's for testing not production
> code.  But that doesn't make the need of its existence any less valid.
> Tests are as much part of the system as the code that runs in the
> deployed system (and in many systems, some of the tests *are* included
> in with and run in the deployed system).

Yup. I just don't have much faith in Gorman finding that argument the
slightest bit interesting, even though it seems pretty obvious to you
and to me and to many here.

J. B. Rainsberger

unread,
Sep 12, 2010, 5:23:00 PM9/12/10
to growing-object-o...@googlegroups.com
On Sun, Sep 12, 2010 at 17:09, Lance Walton
<lance.c...@googlemail.com> wrote:

> I actually don't buy the 'if it's only got one implementation, the interface is redundant' argument any more than the 'if a method is only called from one place it should be inlined' argument. Both give a name to an abstraction and that has enough value for me.

I find two broad reasons to use interfaces: as a seam to introduce
sensible polymorphism and as a seam to enable relayering. Gorman
appears to value only the former. I value that latter, and don't mind
treating it as scaffolding that might never quite disappear. I equate
designing a system more to painting a long suspension bridge (you're
never done, so the scaffolding moves around, but never disappears)
rather than erecting a single building.

Uberto Barbini

unread,
Sep 13, 2010, 5:34:47 AM9/13/10
to growing-object-o...@googlegroups.com
I agree with:
'if it's only got one implementation, and the interface has (more or
less) the same name of implementation, them there is a strong smell
for the interface to be redundant'

I'm thinking about stuff like
Client implements IClient
DaoImpl implements Dao
etc.

cheers

Uberto

J. B. Rainsberger

unread,
Sep 13, 2010, 9:11:24 AM9/13/10
to growing-object-o...@googlegroups.com
On Mon, Sep 13, 2010 at 06:34, Uberto Barbini <ube...@ubiland.net> wrote:
> I agree with:
> 'if it's only got one implementation, and the interface has (more or
> less) the same name of implementation, them there is a strong smell
> for the interface to be redundant'
>
> I'm thinking about stuff like
> Client implements IClient
> DaoImpl implements Dao

Most of the time I can easily figure out what's special about the
production implementation of an interface. When I can't, then I
suspect a layering problem. It usually is.

Kim Gräsman

unread,
Sep 13, 2010, 10:47:29 AM9/13/10
to growing-object-o...@googlegroups.com
Hi there,

On Mon, Sep 13, 2010 at 15:11, J. B. Rainsberger <m...@jbrains.ca> wrote:
> On Mon, Sep 13, 2010 at 06:34, Uberto Barbini <ube...@ubiland.net> wrote:
>> I agree with:
>> 'if it's only got one implementation, and the interface has (more or
>> less) the same name of implementation, them there is a strong smell
>> for the interface to be redundant'
>>
>> I'm thinking about stuff like
>> Client implements IClient
>> DaoImpl implements Dao
>
> Most of the time I can easily figure out what's special about the
> production implementation of an interface. When I can't, then I
> suspect a layering problem. It usually is.

I don't understand your reply. I assume 'layering problem' means
there's some code in one layer that should be in another layer, but I
don't see how that relates to interface/implementation?

Could you give me more context and/or an example?

Many thanks,
- Kim

Reply all
Reply to author
Forward
0 new messages