Groups | Search | Server Info | Keyboard shortcuts | Login | Register [http] [https] [nntp] [nntps]


Groups > comp.lang.java.programmer > #3578 > unrolled thread

"Program to an interface" - When to break a design pattern

Started byZapanaz <http://joecosby.com/code/mail.pl@foo.com>
First post2011-05-05 12:21 -0700
Last post2011-05-10 19:40 -0300
Articles 15 on this page of 75 — 14 participants

Back to article view | Back to comp.lang.java.programmer


Contents

  "Program to an interface" - When to break a design pattern Zapanaz <http://joecosby.com/code/mail.pl@foo.com> - 2011-05-05 12:21 -0700
    Re: "Program to an interface" - When to break a design pattern Joshua Cranmer <Pidgeot18@verizon.invalid> - 2011-05-05 15:43 -0400
      Re: "Program to an interface" - When to break a design pattern Lew <noone@lewscanon.com> - 2011-05-05 17:19 -0400
    Re: "Program to an interface" - When to break a design pattern Daniele Futtorovic <da.futt.news@laposte-dot-net.invalid> - 2011-05-05 21:47 +0200
    Re: "Program to an interface" - When to break a design pattern Jim Janney <jjanney@shell.xmission.com> - 2011-05-05 14:14 -0600
      Re: "Program to an interface" - When to break a design pattern Zapanaz <http://joecosby.com/code/mail.pl@foo.com> - 2011-05-05 13:26 -0700
      Re: "Program to an interface" - When to break a design pattern Daniele Futtorovic <da.futt.news@laposte-dot-net.invalid> - 2011-05-05 22:27 +0200
        Re: "Program to an interface" - When to break a design pattern Jim Janney <jjanney@shell.xmission.com> - 2011-05-05 14:42 -0600
          Re: "Program to an interface" - When to break a design pattern Daniele Futtorovic <da.futt.news@laposte-dot-net.invalid> - 2011-05-05 22:48 +0200
            Re: "Program to an interface" - When to break a design pattern Jim Janney <jjanney@shell.xmission.com> - 2011-05-05 15:02 -0600
              Re: "Program to an interface" - When to break a design pattern Daniele Futtorovic <da.futt.news@laposte-dot-net.invalid> - 2011-05-06 00:02 +0200
                Re: "Program to an interface" - When to break a design pattern Arved Sandstrom <asandstrom3minus1@eastlink.ca> - 2011-05-05 19:49 -0300
                  Re: "Program to an interface" - When to break a design pattern Daniele Futtorovic <da.futt.news@laposte-dot-net.invalid> - 2011-05-06 02:28 +0200
                    Re: "Program to an interface" - When to break a design pattern Arved Sandstrom <asandstrom3minus1@eastlink.ca> - 2011-05-06 07:24 -0300
                      Re: "Program to an interface" - When to break a design pattern Patricia Shanahan <pats@acm.org> - 2011-05-06 07:03 -0700
                        Re: "Program to an interface" - When to break a design pattern Arved Sandstrom <asandstrom3minus1@eastlink.ca> - 2011-05-06 17:30 -0300
                      Re: "Program to an interface" - When to break a design pattern Daniele Futtorovic <da.futt.news@laposte-dot-net.invalid> - 2011-05-06 18:56 +0200
                        Re: "Program to an interface" - When to break a design pattern Arved Sandstrom <asandstrom3minus1@eastlink.ca> - 2011-05-06 17:50 -0300
                          Re: "Program to an interface" - When to break a design pattern Daniele Futtorovic <da.futt.news@laposte-dot-net.invalid> - 2011-05-06 23:37 +0200
                            Re: "Program to an interface" - When to break a design pattern Arved Sandstrom <asandstrom3minus1@eastlink.ca> - 2011-05-06 19:43 -0300
                Re: "Program to an interface" - When to break a design pattern Jim Janney <jjanney@shell.xmission.com> - 2011-05-05 17:17 -0600
                  Re: "Program to an interface" - When to break a design pattern Daniele Futtorovic <da.futt.news@laposte-dot-net.invalid> - 2011-05-06 02:28 +0200
            Re: "Program to an interface" - When to break a design pattern Zapanaz <http://joecosby.com/code/mail.pl@foo.com> - 2011-05-05 23:25 -0700
              Re: "Program to an interface" - When to break a design pattern Daniele Futtorovic <da.futt.news@laposte-dot-net.invalid> - 2011-05-06 18:25 +0200
                Re: "Program to an interface" - When to break a design pattern Zapanaz <http://joecosby.com/code/mail.pl@foo.com> - 2011-05-07 16:26 -0700
                  Re: "Program to an interface" - When to break a design pattern Daniele Futtorovic <da.futt.news@laposte-dot-net.invalid> - 2011-05-08 03:28 +0200
                    Re: "Program to an interface" - When to break a design pattern Arved Sandstrom <asandstrom3minus1@eastlink.ca> - 2011-05-08 00:05 -0300
                      Re: "Program to an interface" - When to break a design pattern Daniele Futtorovic <da.futt.news@laposte-dot-net.invalid> - 2011-05-08 16:15 +0200
                        Re: "Program to an interface" - When to break a design pattern Arved Sandstrom <asandstrom3minus1@eastlink.ca> - 2011-05-08 14:20 -0300
                          Re: "Program to an interface" - When to break a design pattern Daniele Futtorovic <da.futt.news@laposte-dot-net.invalid> - 2011-05-08 19:48 +0200
                            Re: "Program to an interface" - When to break a design pattern markspace <-@.> - 2011-05-10 07:36 -0700
                              Re: "Program to an interface" - When to break a design pattern Jim Janney <jjanney@shell.xmission.com> - 2011-05-10 13:04 -0600
                                Re: "Program to an interface" - When to break a design pattern Daniele Futtorovic <da.futt.news@laposte-dot-net.invalid> - 2011-05-10 21:31 +0200
                              Re: "Program to an interface" - When to break a design pattern Arved Sandstrom <asandstrom3minus1@eastlink.ca> - 2011-05-10 20:01 -0300
                                Re: "Program to an interface" - When to break a design pattern Daniele Futtorovic <da.futt.news@laposte-dot-net.invalid> - 2011-05-11 19:14 +0200
                                Re: "Program to an interface" - When to break a design pattern Patricia Shanahan <pats@acm.org> - 2011-05-11 10:41 -0700
                                  Re: "Program to an interface" - When to break a design pattern Daniele Futtorovic <da.futt.news@laposte-dot-net.invalid> - 2011-05-11 19:55 +0200
                                    Re: "Program to an interface" - When to break a design pattern Lew <noone@lewscanon.com> - 2011-05-11 16:42 -0400
                                      Re: "Program to an interface" - When to break a design pattern Daniele Futtorovic <da.futt.news@laposte-dot-net.invalid> - 2011-05-11 23:34 +0200
                                        Re: "Program to an interface" - When to break a design pattern "John B. Matthews" <nospam@nospam.invalid> - 2011-05-12 00:51 -0400
                                          Re: "Program to an interface" - When to break a design pattern Lew <noone@lewscanon.com> - 2011-05-12 00:58 -0400
                                            Re: "Program to an interface" - When to break a design pattern Tom Anderson <twic@urchin.earth.li> - 2011-05-12 20:08 +0100
                                    Re: "Program to an interface" - When to break a design pattern Arved Sandstrom <asandstrom3minus1@eastlink.ca> - 2011-05-15 13:25 -0300
          Re: "Program to an interface" - When to break a design pattern Lew <noone@lewscanon.com> - 2011-05-05 17:24 -0400
            Re: "Program to an interface" - When to break a design pattern Jim Janney <jjanney@shell.xmission.com> - 2011-05-05 16:00 -0600
            Re: "Program to an interface" - When to break a design pattern Jukka Lahtinen <jtfjdehf@hotmail.com.invalid> - 2011-05-06 15:01 +0300
              Re: "Program to an interface" - When to break a design pattern Lew <noone@lewscanon.com> - 2011-05-06 12:17 -0400
                Re: "Program to an interface" - When to break a design pattern Zapanaz <http://joecosby.com/code/mail.pl@foo.com> - 2011-05-07 16:28 -0700
      Re: "Program to an interface" - When to break a design pattern Lew <noone@lewscanon.com> - 2011-05-05 17:21 -0400
        Re: "Program to an interface" - When to break a design pattern Jim Janney <jjanney@shell.xmission.com> - 2011-05-05 15:58 -0600
          Re: "Program to an interface" - When to break a design pattern Lew <noone@lewscanon.com> - 2011-05-05 18:18 -0400
        Re: "Program to an interface" - When to break a design pattern Arved Sandstrom <asandstrom3minus1@eastlink.ca> - 2011-05-05 19:20 -0300
          Re: "Program to an interface" - When to break a design pattern Lew <noone@lewscanon.com> - 2011-05-05 18:23 -0400
            Re: "Program to an interface" - When to break a design pattern Arved Sandstrom <asandstrom3minus1@eastlink.ca> - 2011-05-05 20:17 -0300
    Re: "Program to an interface" - When to break a design pattern Arved Sandstrom <asandstrom3minus1@eastlink.ca> - 2011-05-05 18:26 -0300
    Re: "Program to an interface" - When to break a design pattern Steven Simpson <ss@domain.invalid> - 2011-05-05 22:57 +0100
      Re: "Program to an interface" - When to break a design pattern Tom Anderson <twic@urchin.earth.li> - 2011-05-05 23:29 +0100
        Re: "Program to an interface" - When to break a design pattern Steven Simpson <ss@domain.invalid> - 2011-05-06 13:30 +0100
          Re: "Program to an interface" - When to break a design pattern Lew <noone@lewscanon.com> - 2011-05-06 12:19 -0400
      Re: "Program to an interface" - When to break a design pattern Jim Janney <jjanney@shell.xmission.com> - 2011-05-05 16:41 -0600
        Re: "Program to an interface" - When to break a design pattern Arved Sandstrom <asandstrom3minus1@eastlink.ca> - 2011-05-05 20:47 -0300
    Re: "Program to an interface" - When to break a design pattern Roedy Green <see_website@mindprod.com.invalid> - 2011-05-05 16:41 -0700
      Re: "Program to an interface" - When to break a design pattern Jim Janney <jjanney@shell.xmission.com> - 2011-05-05 22:47 -0600
      Re: "Program to an interface" - When to break a design pattern Zapanaz <http://joecosby.com/code/mail.pl@foo.com> - 2011-05-05 23:28 -0700
    Re: "Program to an interface" - When to break a design pattern Michal Kleczek <kleku75@gmail.com> - 2011-05-06 17:15 +0200
      Re: "Program to an interface" - When to break a design pattern Arved Sandstrom <asandstrom3minus1@eastlink.ca> - 2011-05-06 20:53 -0300
        Re: "Program to an interface" - When to break a design pattern Lew <noone@lewscanon.com> - 2011-05-06 21:39 -0400
          Re: "Program to an interface" - When to break a design pattern Arved Sandstrom <asandstrom3minus1@eastlink.ca> - 2011-05-07 00:56 -0300
        Re: "Program to an interface" - When to break a design pattern Michal Kleczek <kleku75@gmail.com> - 2011-05-08 12:24 +0200
          Re: "Program to an interface" - When to break a design pattern Arved Sandstrom <asandstrom3minus1@eastlink.ca> - 2011-05-08 13:42 -0300
            Re: "Program to an interface" - When to break a design pattern Michal Kleczek <kleku75@gmail.com> - 2011-05-09 11:04 +0200
              Re: "Program to an interface" - When to break a design pattern Arved Sandstrom <asandstrom3minus1@eastlink.ca> - 2011-05-09 19:33 -0300
                Re: "Program to an interface" - When to break a design pattern Michal Kleczek <kleku75@gmail.com> - 2011-05-10 15:51 +0200
                  Re: "Program to an interface" - When to break a design pattern Jim Janney <jjanney@shell.xmission.com> - 2011-05-10 13:15 -0600
                  Re: "Program to an interface" - When to break a design pattern Arved Sandstrom <asandstrom3minus1@eastlink.ca> - 2011-05-10 19:40 -0300

Page 4 of 4 — ← Prev page 1 2 3 [4]


#3623

FromArved Sandstrom <asandstrom3minus1@eastlink.ca>
Date2011-05-05 20:47 -0300
Message-ID<ZFGwp.9374$h%4.4784@newsfe22.iad>
In reply to#3617
On 11-05-05 07:41 PM, Jim Janney wrote:
> Steven Simpson <ss@domain.invalid> writes:
[ SNIP ]

>> OTOH, this sort of thing is already done, with Set and Collection.  Set
>> extends Collection, but doesn't actually define any new methods.  (It
>> does take advantage of 'overriding' the documentation, though.)  Is it
>> worth having Set if:
>>
>>     * you can implement Set without actually having set semantics?
>>     * you can implement set semantics with just Collection?
>>
>> So, if you're prepared to trust that an implementation of Set or
>> InsertionOrderedMap follows the documented rules that can't be
>> compiler-enforced, perhaps it's as well do away with those interfaces,
>> and just put the documentation on methods like getSortedMap, and trust
>> that they are implemented accordingly.
> 
> That may be the best overall approach.  The Javadoc for java.util.Map
> explicitly notes that different implementations can provide different
> behavior here.
> 
Which is actually the case for a bunch of collections. Of relevance to
this thread, LinkedHashMap provides 4 new method implementations, but 3
of them are overrides of methods in concrete class HashMap. Those 3 in
turn are overrides of method implementations in AbstractMap. The two
instantiable classes have different behaviour, though, so if I decide
that it's really LinkedHashMap that I need, another Map will not do. So
why refer to it as a Map?

With Java collections, one may pass around a Map or a Set or a List,
with reasonable trust that whatever is being shuttled around has
high-level map/set/bag semantics, but many/most Java programmers also
care a fair bit about the actual implementations used, because it
matters. They behave differently. They may all be Maps or Sets or Lists,
but they're not the same. It frequently is not acceptable to pass around
just any Map or Set or List, so why is "program to the interface" so
highly touted here? Beats me.

My 2 cents worth. And I'm being a bit of non-conformist and shit
disturber here. :-)

And rather than rely only on documentation, what's wrong with using the
language? I've picked ConcurrentHashMap, say, because I damned well need
ConcurrentHashMap, and I want and require getAppropriateMap() to return
a ConcurrentHashMap, so perhaps it is the proper thing to have getMap()
return ConcurrentHashMap.

Just a thought. I hearken back to your earlier observation, that:

"The point of programming to the interface is to make it easier to
substitute a different implementation, which implies that any reasonable
implementation can be used.  If this is not true, if the code that uses
the object relies on behavior only found in one implementation, then
there is no benefit to using the interface, and you make it more
inviting for someone to break things later on."

This is absolutely true. And the Java Collections API is rife with
possibilities for where "programming to the interface" is undesirable
and counterproductive.

AHS

[toc] | [prev] | [next] | [standalone]


#3622

FromRoedy Green <see_website@mindprod.com.invalid>
Date2011-05-05 16:41 -0700
Message-ID<v3d6s6li6rgq2u28pversmjl1l913fjf0i@4ax.com>
In reply to#3578
On Thu, 05 May 2011 12:21:55 -0700, Zapanaz
<http://joecosby.com/code/mail.pl@foo.com> wrote, quoted or indirectly
quoted someone who said :

>The problem is, where I'm creating sortedMap above, I need the map to
>retain the insertion order. If what's returned actually is a Map,
>rather than a LinkedHashMap, then the results the user actually sees
>are going to be in the wrong order. Making things worse, in this case,
>nothing would actually break, only the end user would notice anything
>was actually wrong.

The idea of an interface is you should be able to substitute some
other implementation and all should work unmodified.  That is not the
case with the interface you chose.  You need to either find or create
an interface that nails down all the desired behaviour, or use the
original actual implementation.

I am not a big fan of this pattern for the following reasons:
1. it slows down access.
2. it obfuscates just what the code is using NOW for the
implementation.
3. It is more verbose, giving you one more thing you have to eyeball
carefully and make dance through the genericity hoops. That makes for
buggier code.

The main place it would pay off is if you plan to later do some fine
tuning, and want to leave open the option of easily substituting your
own tuned collection classes.
-- 
Roedy Green Canadian Mind Products
http://mindprod.com
Politicians complain that Kindles and iBooks are killing jobs by 
destroying the paper book industry.  I see it that they have create a way 
to produce books for less than a third the cost without destroying forests 
and emitting greenhouse gases in the process.  They have created wealth.  
They are encouraging literacy and cutting the costs of education.  

[toc] | [prev] | [next] | [standalone]


#3638

FromJim Janney <jjanney@shell.xmission.com>
Date2011-05-05 22:47 -0600
Message-ID<2pr58co2pb.fsf@shell.xmission.com>
In reply to#3622
Roedy Green <see_website@mindprod.com.invalid> writes:

> On Thu, 05 May 2011 12:21:55 -0700, Zapanaz
> <http://joecosby.com/code/mail.pl@foo.com> wrote, quoted or indirectly
> quoted someone who said :
>
>>The problem is, where I'm creating sortedMap above, I need the map to
>>retain the insertion order. If what's returned actually is a Map,
>>rather than a LinkedHashMap, then the results the user actually sees
>>are going to be in the wrong order. Making things worse, in this case,
>>nothing would actually break, only the end user would notice anything
>>was actually wrong.
>
> The idea of an interface is you should be able to substitute some
> other implementation and all should work unmodified.  That is not the
> case with the interface you chose.  You need to either find or create
> an interface that nails down all the desired behaviour, or use the
> original actual implementation.
>
> I am not a big fan of this pattern for the following reasons:
> 1. it slows down access.
> 2. it obfuscates just what the code is using NOW for the
> implementation.
> 3. It is more verbose, giving you one more thing you have to eyeball
> carefully and make dance through the genericity hoops. That makes for
> buggier code.
>
> The main place it would pay off is if you plan to later do some fine
> tuning, and want to leave open the option of easily substituting your
> own tuned collection classes.

Wandering off the original topic, this might interest you if you haven't
already seen it, on the subject of deciding when to break rules:

http://www.miller-mccune.com/culture-society/triumph-of-the-cyborg-composer-8507

-- 
Jim Janney

[toc] | [prev] | [next] | [standalone]


#3640

FromZapanaz <http://joecosby.com/code/mail.pl@foo.com>
Date2011-05-05 23:28 -0700
Message-ID<b757s6ltvk2nld4t6nkfsgkb91grccn0er@4ax.com>
In reply to#3622
On Thu, 05 May 2011 16:41:33 -0700, Roedy Green
<see_website@mindprod.com.invalid> wrote:

>On Thu, 05 May 2011 12:21:55 -0700, Zapanaz
><http://joecosby.com/code/mail.pl@foo.com> wrote, quoted or indirectly
>quoted someone who said :
>
>>The problem is, where I'm creating sortedMap above, I need the map to
>>retain the insertion order. If what's returned actually is a Map,
>>rather than a LinkedHashMap, then the results the user actually sees
>>are going to be in the wrong order. Making things worse, in this case,
>>nothing would actually break, only the end user would notice anything
>>was actually wrong.
>
>The idea of an interface is you should be able to substitute some
>other implementation and all should work unmodified.  That is not the
>case with the interface you chose.  You need to either find or create
>an interface that nails down all the desired behaviour, or use the
>original actual implementation.
>
>I am not a big fan of this pattern for the following reasons:
>1. it slows down access.
>2. it obfuscates just what the code is using NOW for the
>implementation.
>3. It is more verbose, giving you one more thing you have to eyeball
>carefully and make dance through the genericity hoops. That makes for
>buggier code.
>
>The main place it would pay off is if you plan to later do some fine
>tuning, and want to leave open the option of easily substituting your
>own tuned collection classes.

Thanks Roedy.

Your web page was a lot of help to me when I was learning Java years
ago, thanks for that too.

-- 
Zapanaz
International Satanic Conspiracy
Customer Support Specialist
http://joecosby.com/ 
Isn't round the funny side that never ends?

:: Currently listening to For His Namesake, by Amboy Dukes/Ted Nugent, from "Journey to the Center of the Mind"

[toc] | [prev] | [next] | [standalone]


#3689

FromMichal Kleczek <kleku75@gmail.com>
Date2011-05-06 17:15 +0200
Message-ID<iq139v$feg$1@news.onet.pl>
In reply to#3578
 wrote:

> 
> I've seen this design pattern before
> 
> http://witte-consulting.com/documents/design-principles/
> 
> and, in general, I see the point of it.
> 
> But say we've got something like this
> 
> LinkedHashMap<String, Integer> sortedMap = this.getSortedMap();
> 
> So you have the method
> 
> public LinkedHashMap<String, Integer> getSortedMap() {
>   //do stuff
> }
> 
> (not necessarily public)
> 
> Now the design principle says, the method signature should instead be
> 
> public Map<String, Integer> getSortedMap() {
>   //do stuff
> }
> 
> The problem is, where I'm creating sortedMap above, I need the map to
> retain the insertion order. If what's returned actually is a Map,
> rather than a LinkedHashMap, then the results the user actually sees
> are going to be in the wrong order. Making things worse, in this case,
> nothing would actually break, only the end user would notice anything
> was actually wrong.
> 
> So in this case, it seems to me, that using LinkedHashMap in the
> method signature makes sense. The fact that the return retains the
> insertion order is an integral part of what the method does.
> 
> If nothing else, it's going to save Fred Developer down the line from
> looking at the code around this
> 
> Map<String, Integer> sortedMap = this.getSortedMap();
> 
> and thinking "wait, how do I know getSortedMap() is going to return a
> result with the right ordering?", and having to waste time digging
> into that method.
> 
> ***
> 
> Opinions? Angry mob with torches and pitchforks? The Spanish
> Inquisition?
> 
> 

Stick to the principle and specify return type as java.util.Map.

The decision on what Map implementation to use has to obey DRY principle - 
if the place to decide is getSortedMap() then the rest of the program should 
assume getSortedMap() does the right thing.

Imagine the requirements change and from now on the map has to retain 
reverse insertion order. Do you want to rewrite your clients?

-- 
Michal

[toc] | [prev] | [next] | [standalone]


#3727

FromArved Sandstrom <asandstrom3minus1@eastlink.ca>
Date2011-05-06 20:53 -0300
Message-ID<GR%wp.68076$yp3.20908@newsfe09.iad>
In reply to#3689
On 11-05-06 12:15 PM, Michal Kleczek wrote:
>  wrote:
> 
>>
>> I've seen this design pattern before
>>
>> http://witte-consulting.com/documents/design-principles/
>>
>> and, in general, I see the point of it.
>>
>> But say we've got something like this
>>
>> LinkedHashMap<String, Integer> sortedMap = this.getSortedMap();
>>
>> So you have the method
>>
>> public LinkedHashMap<String, Integer> getSortedMap() {
>>   //do stuff
>> }
>>
>> (not necessarily public)
>>
>> Now the design principle says, the method signature should instead be
>>
>> public Map<String, Integer> getSortedMap() {
>>   //do stuff
>> }
>>
>> The problem is, where I'm creating sortedMap above, I need the map to
>> retain the insertion order. If what's returned actually is a Map,
>> rather than a LinkedHashMap, then the results the user actually sees
>> are going to be in the wrong order. Making things worse, in this case,
>> nothing would actually break, only the end user would notice anything
>> was actually wrong.
>>
>> So in this case, it seems to me, that using LinkedHashMap in the
>> method signature makes sense. The fact that the return retains the
>> insertion order is an integral part of what the method does.
>>
>> If nothing else, it's going to save Fred Developer down the line from
>> looking at the code around this
>>
>> Map<String, Integer> sortedMap = this.getSortedMap();
>>
>> and thinking "wait, how do I know getSortedMap() is going to return a
>> result with the right ordering?", and having to waste time digging
>> into that method.
>>
>> ***
>>
>> Opinions? Angry mob with torches and pitchforks? The Spanish
>> Inquisition?
> 
> Stick to the principle and specify return type as java.util.Map.

It's best to understand that principle before urging it on people. No
less an authority than Erich Gamma has made it clear - albeit not widely
enough nor early enough - that when GOF said "program to an interface",
they did *NOT* mean only Java "interface" as in a construct with the
"interface" keyword. What they actually meant was the OOP interface that
*every* class has, coupled with a judicious choice of which interface of
this type to pick in the type hierarchy.

What the principle really means - and you don't have to take my word for
it, you can look up discussions by OOP authorities - is that given that
the object you need is in a type hierarchy - classes, abstract classes,
interfaces - that you pick that level in the type hierarchy to work
with, which is as high up as possible while still meeting requirements.

The highest interface that fits the bill might actually be the interface
of a concrete class, or the interface of an abstract class. In fact
abstract classes are frequently better as interfaces than actual Java
"interfaces".

Bear in mind - and this is not invented by me; you can find this if you
keep up on OOP literature - that there is a reasonably well-known
distinction also between public and published interfaces (look up
"Fowler", "public", "published", and continue to keep in mind that
"interface" doesn't mean the Java keyword). If an interface is published
then it's not a bad thing to use it. LinkedHashMap has a published
interface *and* it has behaviour that other maps do not have - it is a
correct decision to stop in the type hierarchy with LinkedHashMap if
that's the behaviour you need.

Further note: behaviour isn't just a list of method signatures. It's
also what the abstract class or concrete class actually does. Not *how*
it does it - that's implementation - but what it does - that's
contractual _behaviour_. Keeping insertion order for iterators is
_behaviour_...using a doubly-linked list to accomplish that is
implementation.

> The decision on what Map implementation to use has to obey DRY principle - 
> if the place to decide is getSortedMap() then the rest of the program should 
> assume getSortedMap() does the right thing.

Good luck with that one. That's what a lot of Java code ends up hoping
for, because people misunderstood "program to an interface" and forced
the use of the highest possible level Java-keyword interfaces everywhere
possible. There are a bunch of problems that come about then:
downcasting all over the place, brittle code because now everything that
relied on interface X (including the 10 classes you wrote that
implemented it) has to be changed because you need to add a method to
interface X (or modify a method signature in interface X), calling code
unaware that it really ended up depending on that Map actually being a
LinkedHashMap and only finding out when some other provider of the
method gets swapped in...the list goes on and on.

> Imagine the requirements change and from now on the map has to retain 
> reverse insertion order. Do you want to rewrite your clients?
> 
Bad example in my opinion. The first time this happened I'd take it on
the chin and accept that the client code doesn't know what it
wants...seeing as how it's the client code that forces a change like
this. And rather than be screwed twice I'd probably write an abstract
class, or Java-keyword interface, that would let me cope with poor
design by the other team.

Be clear on this - you could have used a high-level Java "interface", as
in the keyword type of interface. And the requirements change and now
you need to modify the interface - you're just as hosed then, Michal.

AHS

[toc] | [prev] | [next] | [standalone]


#3735

FromLew <noone@lewscanon.com>
Date2011-05-06 21:39 -0400
Message-ID<iq27rs$ehs$1@news.albasani.net>
In reply to#3727
On 05/06/2011 07:53 PM, Arved Sandstrom wrote:
> On 11-05-06 12:15 PM, Michal Kleczek wrote:
>>   wrote:
>>
>>>
>>> I've seen this design pattern before
>>>
>>> http://witte-consulting.com/documents/design-principles/
>>>
>>> and, in general, I see the point of it.
>>>
>>> But say we've got something like this
>>>
>>> LinkedHashMap<String, Integer>  sortedMap = this.getSortedMap();
>>>
>>> So you have the method
>>>
>>> public LinkedHashMap<String, Integer>  getSortedMap() {
>>>    //do stuff
>>> }
>>>
>>> (not necessarily public)
>>>
>>> Now the design principle says, the method signature should instead be
>>>
>>> public Map<String, Integer>  getSortedMap() {
>>>    //do stuff
>>> }
>>>
>>> The problem is, where I'm creating sortedMap above, I need the map to
>>> retain the insertion order. If what's returned actually is a Map,
>>> rather than a LinkedHashMap, then the results the user actually sees
>>> are going to be in the wrong order. Making things worse, in this case,
>>> nothing would actually break, only the end user would notice anything
>>> was actually wrong.
>>>
>>> So in this case, it seems to me, that using LinkedHashMap in the
>>> method signature makes sense. The fact that the return retains the
>>> insertion order is an integral part of what the method does.
>>>
>>> If nothing else, it's going to save Fred Developer down the line from
>>> looking at the code around this
>>>
>>> Map<String, Integer>  sortedMap = this.getSortedMap();
>>>
>>> and thinking "wait, how do I know getSortedMap() is going to return a
>>> result with the right ordering?", and having to waste time digging
>>> into that method.
>>>
>>> ***
>>>
>>> Opinions? Angry mob with torches and pitchforks? The Spanish
>>> Inquisition?
>>
>> Stick to the principle and specify return type as java.util.Map.
>
> It's best to understand that principle before urging it on people. No
> less an authority than Erich Gamma has made it clear - albeit not widely
> enough nor early enough - that when GOF said "program to an interface",
> they did *NOT* mean only Java "interface" as in a construct with the
> "interface" keyword. What they actually meant was the OOP interface that
> *every* class has, coupled with a judicious choice of which interface of
> this type to pick in the type hierarchy.
>
> What the principle really means - and you don't have to take my word for
> it, you can look up discussions by OOP authorities - is that given that
> the object you need is in a type hierarchy - classes, abstract classes,
> interfaces - that you pick that level in the type hierarchy to work
> with, which is as high up as possible while still meeting requirements.
>
> The highest interface that fits the bill might actually be the interface
> of a concrete class, or the interface of an abstract class. In fact
> abstract classes are frequently better as interfaces than actual Java
> "interfaces".
>
> Bear in mind - and this is not invented by me; you can find this if you
> keep up on OOP literature - that there is a reasonably well-known
> distinction also between public and published interfaces (look up
> "Fowler", "public", "published", and continue to keep in mind that
> "interface" doesn't mean the Java keyword). If an interface is published
> then it's not a bad thing to use it. LinkedHashMap has a published
> interface *and* it has behaviour that other maps do not have - it is a
> correct decision to stop in the type hierarchy with LinkedHashMap if
> that's the behaviour you need.
>
> Further note: behaviour isn't just a list of method signatures. It's
> also what the abstract class or concrete class actually does. Not *how*
> it does it - that's implementation - but what it does - that's
> contractual _behaviour_. Keeping insertion order for iterators is
> _behaviour_...using a doubly-linked list to accomplish that is
> implementation.
>
>> The decision on what Map implementation to use has to obey DRY principle -
>> if the place to decide is getSortedMap() then the rest of the program should
>> assume getSortedMap() does the right thing.
>
> Good luck with that one. That's what a lot of Java code ends up hoping
> for, because people misunderstood "program to an interface" and forced
> the use of the highest possible level Java-keyword interfaces everywhere
> possible. There are a bunch of problems that come about then:
> downcasting all over the place, brittle code because now everything that
> relied on interface X (including the 10 classes you wrote that
> implemented it) has to be changed because you need to add a method to
> interface X (or modify a method signature in interface X), calling code
> unaware that it really ended up depending on that Map actually being a
> LinkedHashMap and only finding out when some other provider of the
> method gets swapped in...the list goes on and on.
>
>> Imagine the requirements change and from now on the map has to retain
>> reverse insertion order. Do you want to rewrite your clients?
>>
> Bad example in my opinion. The first time this happened I'd take it on
> the chin and accept that the client code doesn't know what it
> wants...seeing as how it's the client code that forces a change like
> this. And rather than be screwed twice I'd probably write an abstract
> class, or Java-keyword interface, that would let me cope with poor
> design by the other team.
>
> Be clear on this - you could have used a high-level Java "interface", as
> in the keyword type of interface. And the requirements change and now
> you need to modify the interface - you're just as hosed then, Michal.

Here are the relevant chapter titles from /Effective Java/, by Joshua Bloch:
Item 18: Prefer interfaces to abstract classes
Item 19: Use interfaces only to define types
Item 52: Refer to objects by their interfaces
Item 53: Prefer interfaces to reflection

Here he refers to the Java 'interface', not the more general term you just 
discussed.

Note that in the details of Item 52, Mr. Bloch covers using the more specific 
types when the contract (the GoF sense of "interface") calls for it:

"If appropriate interface types exist, then ... your program will be more 
flexible if you use the interface to refer to the object; if not, just use the 
least specific class in the class hierarchy that provides the required 
functionality."


-- 
Lew
Honi soit qui mal y pense.
http://upload.wikimedia.org/wikipedia/commons/c/cf/Friz.jpg

[toc] | [prev] | [next] | [standalone]


#3743

FromArved Sandstrom <asandstrom3minus1@eastlink.ca>
Date2011-05-07 00:56 -0300
Message-ID<Ep3xp.13901$Du7.6572@newsfe04.iad>
In reply to#3735
On 11-05-06 10:39 PM, Lew wrote:
> On 05/06/2011 07:53 PM, Arved Sandstrom wrote:
[ SNIP ]

> Here are the relevant chapter titles from /Effective Java/, by Joshua
> Bloch:
> Item 18: Prefer interfaces to abstract classes
> Item 19: Use interfaces only to define types
> Item 52: Refer to objects by their interfaces
> Item 53: Prefer interfaces to reflection
> 
> Here he refers to the Java 'interface', not the more general term you
> just discussed.
> 
> Note that in the details of Item 52, Mr. Bloch covers using the more
> specific types when the contract (the GoF sense of "interface") calls
> for it:
> 
> "If appropriate interface types exist, then ... your program will be
> more flexible if you use the interface to refer to the object; if not,
> just use the least specific class in the class hierarchy that provides
> the required functionality."

Fair enough. As far as Item 52 goes, I think that's what everyone is
saying, given that elaboration you quoted. Item 19, no argument from me.
Item 53, I won't argue about that either.

Item 18, "prefer interfaces to abstract classes" is a short & sweet
recommendation that more often than not is a good one to follow.
Particularly in Java, where language limitations, as Bloch himself
points out, seriously limit the use of abstract classes as type
definitions. However, the use of the word "prefer" means to me that
available interfaces are used over available abstract classes when
consideration shows that it's the best choice, not just because a
single-sentence principle says so.

One important thing needs to be pointed out here, and it's mentioned in
Item 18 by Bloch: " Any class that defines all of the required methods
and obeys the general contract is permitted to implement an interface".
The sticking point in this thread is the _general contract_ - there is
no interface, Map or otherwise, that has the contract required by the
OP. Short of defining a PredictableIterationOrderMap interface and
having a subclass of LinkedHashMap implement that, one may as well use
LinkedHashMap. Per Bloch's Item 52 - there is no appropriate interface
type available here.

To rephrase that, we should be choosing types - interfaces, abstract
classes, or concrete classes - whose contracts match the requirements.
And a bag of method signatures is not a contract (except between the
code and the compiler). Behaviour specified in the API Javadocs (in the
case of maps, starting right with java.util.Map) is the actual contract.

The practise of using a Java interface at all costs, and the most
general interface at that, with little or no attention paid to the fact
that the general type you are passing around does not have a required
contract, is so prevalent in the industry that these days, if you try to
point out the intent of the design principle, people often have no clue
what you are trying to express. It's a losing battle. There's certainly
no shortage of folks who think that that "bag of method signatures" _is_
the contract, that's for sure.

AHS

[toc] | [prev] | [next] | [standalone]


#3800

FromMichal Kleczek <kleku75@gmail.com>
Date2011-05-08 12:24 +0200
Message-ID<iq5r0f$il6$1@news.onet.pl>
In reply to#3727
Arved Sandstrom wrote:

> 
> Further note: behaviour isn't just a list of method signatures. It's
> also what the abstract class or concrete class actually does. Not *how*
> it does it - that's implementation - but what it does - that's
> contractual _behaviour_. Keeping insertion order for iterators is
> _behaviour_...using a doubly-linked list to accomplish that is
> implementation.
> 

I think this is the real point of the discussion - Java interfaces are just 
too weak to express contracts. Note that there are many other aspects beside 
iteration ordering that are important to the overall solution but still not 
expressed (and not expressable) by interfaces: concurrency guarantees, 
performance and memory usage characteristics etc.
Picking one aspect and trying to express it using Java types just does not 
make sense.

One could actually argue if java.util.Set interface is really needed at all.

Additionally - the mere fact that in the overall solution the choice of the 
map implementation having a particular characteristic is important is not 
enough to justify that _all_ code should depend on it.

>> The decision on what Map implementation to use has to obey DRY principle
>> - if the place to decide is getSortedMap() then the rest of the program
>> should assume getSortedMap() does the right thing.
> 
> Good luck with that one. That's what a lot of Java code ends up hoping
> for, because people misunderstood "program to an interface" and forced
> the use of the highest possible level Java-keyword interfaces everywheres
> possible. There are a bunch of problems that come about then:
> downcasting all over the place, 

If downcasting is needed it means the wrong type was choosen. It is not the 
case here since OP is not going to use any methods not defined in 
java.util.Map.

-- 
Michal

[toc] | [prev] | [next] | [standalone]


#3816

FromArved Sandstrom <asandstrom3minus1@eastlink.ca>
Date2011-05-08 13:42 -0300
Message-ID<JJzxp.21021$uh5.14366@newsfe02.iad>
In reply to#3800
On 11-05-08 07:24 AM, Michal Kleczek wrote:
> Arved Sandstrom wrote:
> 
>> Further note: behaviour isn't just a list of method signatures. It's
>> also what the abstract class or concrete class actually does. Not *how*
>> it does it - that's implementation - but what it does - that's
>> contractual _behaviour_. Keeping insertion order for iterators is
>> _behaviour_...using a doubly-linked list to accomplish that is
>> implementation.
> 
> I think this is the real point of the discussion - Java interfaces are just 
> too weak to express contracts. Note that there are many other aspects beside 
> iteration ordering that are important to the overall solution but still not 
> expressed (and not expressable) by interfaces: concurrency guarantees, 
> performance and memory usage characteristics etc.
> Picking one aspect and trying to express it using Java types just does not 
> make sense.

Agreed, partly. It can't be done with Java interfaces at all. It can -
obviously - be done with the published API of abstract or concrete Java
classes.

What we're really arguing about here is whether it's desirable to bind
client code to provider contracts. It's clear that Map cannot enforce a
behavioural contract, and that LinkedHashMap does. Rather than beat that
to death, let's acknowledge that we have one camp that argues that we
don't want to tie the caller to a behavioural provider contract, and
another camp (me) that says that sometimes you do want and need to do this.

> One could actually argue if java.util.Set interface is really needed at all.

This is one of the main points, I agree. It's also been highlighted in
this thread precisely because most of the time the calling code
genuinely doesn't care what implementation it gets. Most of the time the
calling code requires simply that it gets a Map, List, Set etc, and the
provider of the Map or List or Set has the responsibility for enforcing
the contract...assuming one exists.

In this case I believe a credible case can be made that the calling code
does care about what the specific contract is: the OP said so, and
provided a good use case. One thing I do know, based on experience, is
that if you return a generic map from that method, that when developers
move on to different projects and different employers, and the
documentation (if it ever existed) fails to be maintained, and
refactorings change the relationship of the Map provider code to the
calling code, that sooner or later that client code is no longer going
to get a LinkedHashMap. If the code never gets touched again after
Version 1.0, then you were just _lucky_.

I don't pretend to be infallible when it comes to answers for this kind
of thing. But I do know that a knee-jerk 100% adherence to "program to a
Java 'interface'", and highest-level interfaces at that, can be wrong.

Absolutely, Java interfaces, *as language constructs* that are enforced
by the compiler, are too weak to express many forms of contracts. All
they can do is ensure that subtypes that implement an interface have a
certain set of methods. Period.

> Additionally - the mere fact that in the overall solution the choice of the 
> map implementation having a particular characteristic is important is not 
> enough to justify that _all_ code should depend on it.

I'd honestly need to see more of the OP's problem before I definitely
recommended returning LinkedHashMap. Mainly what got my hackles up was
everyone piling in on the "program to the interface" principle without
any obvious thought being put into it.

Fact of the matter is that you _could_ return Map in the OP's scenario,
and get away with it, provided that both the code that constructed and
provided that map, and the code that used it, were one monolithic piece.
It's when you separate the two that wishful thinking enters the picture.
We don't in this case know enough about the relationship of the provider
of the map and the user of the map to say, one way or the other, whether
Map or LinkedHashMap is the best way to go.

>>> The decision on what Map implementation to use has to obey DRY principle
>>> - if the place to decide is getSortedMap() then the rest of the program
>>> should assume getSortedMap() does the right thing.
>>
>> Good luck with that one. That's what a lot of Java code ends up hoping
>> for, because people misunderstood "program to an interface" and forced
>> the use of the highest possible level Java-keyword interfaces everywheres
>> possible. There are a bunch of problems that come about then:
>> downcasting all over the place, 
> 
> If downcasting is needed it means the wrong type was choosen. It is not the 
> case here since OP is not going to use any methods not defined in 
> java.util.Map.
> 
With Java collections - Map and Collection mainly - you normally don't
have to downcast, just for the reason you stated. All the subinterfaces
and classes that extend/implement Map and Collection rarely
significantly change the actual set of method signatures, with a few
notable exceptions like queues. But if you "program to an interface" at
all costs in many other type hierarchies then it can happen.

As a conclusion, I think a few of us have at least agreed that there is
no good mechanism in Java for defining and enforcing a large swathe of
contractual behaviour. We rely on good Javadocs, and meticulous reading
of same, and very good adherence to design and implementation best
practices - all those things that all Java programmers are so very good
at - to save us.

AHS

[toc] | [prev] | [next] | [standalone]


#3846

FromMichal Kleczek <kleku75@gmail.com>
Date2011-05-09 11:04 +0200
Message-ID<iq8an1$ssl$1@news.onet.pl>
In reply to#3816
Arved Sandstrom wrote:

> On 11-05-08 07:24 AM, Michal Kleczek wrote:
>> Arved Sandstrom wrote:
>> 
>>> Further note: behaviour isn't just a list of method signatures. It's
>>> also what the abstract class or concrete class actually does. Not *how*
>>> it does it - that's implementation - but what it does - that's
>>> contractual _behaviour_. Keeping insertion order for iterators is
>>> _behaviour_...using a doubly-linked list to accomplish that is
>>> implementation.
>> 
>> I think this is the real point of the discussion - Java interfaces are
>> just too weak to express contracts. Note that there are many other
>> aspects beside iteration ordering that are important to the overall
>> solution but still not expressed (and not expressable) by interfaces:
>> concurrency guarantees, performance and memory usage characteristics etc.
>> Picking one aspect and trying to express it using Java types just does
>> not make sense.
> 
> Agreed, partly. It can't be done with Java interfaces at all. It can -
> obviously - be done with the published API of abstract or concrete Java
> classes.

Then it would be not "what" but "how".

> 
> What we're really arguing about here is whether it's desirable to bind
> client code to provider contracts. It's clear that Map cannot enforce a
> behavioural contract, and that LinkedHashMap does. Rather than beat that
> to death, let's acknowledge that we have one camp that argues that we
> don't want to tie the caller to a behavioural provider contract, and
> another camp (me) that says that sometimes you do want and need to do
> this.

I think you are missing the fact that the client is _already_ tied to a 
contract by calling getSortedMap() to get the map (since the contract of 
getSortedMap() is "return a map implementation that provides such and such 
iteration order".
The question is rather - do we need to specify this contract as a Java type?
I would rather say: since the compiler cannot enforce/check the contract 
anyway then it is useless - the contract specified as documentation of 
getSortedMap() is enough.

-- 
Michal

[toc] | [prev] | [next] | [standalone]


#3879

FromArved Sandstrom <asandstrom3minus1@eastlink.ca>
Date2011-05-09 19:33 -0300
Message-ID<sZZxp.15218$Du7.4644@newsfe04.iad>
In reply to#3846
On 11-05-09 06:04 AM, Michal Kleczek wrote:
> Arved Sandstrom wrote:
> 
>> On 11-05-08 07:24 AM, Michal Kleczek wrote:
>>> Arved Sandstrom wrote:
>>>
>>>> Further note: behaviour isn't just a list of method signatures. It's
>>>> also what the abstract class or concrete class actually does. Not *how*
>>>> it does it - that's implementation - but what it does - that's
>>>> contractual _behaviour_. Keeping insertion order for iterators is
>>>> _behaviour_...using a doubly-linked list to accomplish that is
>>>> implementation.
>>>
>>> I think this is the real point of the discussion - Java interfaces are
>>> just too weak to express contracts. Note that there are many other
>>> aspects beside iteration ordering that are important to the overall
>>> solution but still not expressed (and not expressable) by interfaces:
>>> concurrency guarantees, performance and memory usage characteristics etc.
>>> Picking one aspect and trying to express it using Java types just does
>>> not make sense.
>>
>> Agreed, partly. It can't be done with Java interfaces at all. It can -
>> obviously - be done with the published API of abstract or concrete Java
>> classes.
> 
> Then it would be not "what" but "how".

No, that's not necessarily so. Abstract classes and concrete classes
provide both a "what" - an interface (as in contract, not Java keyword)
- and an implementation. An abstract class with no method
implementations actually ought to be a Java interface, but assuming we
have one, it's 100% "what" and 0% "how". An abstract class may trend
quite high, 70 or 80 or 90 percent, in "how", but it's still 100% in
"what", assuming that we consider all the public methods to be part of a
published API.

Even a concrete class - again assuming that all of its public methods
are part of a published API - is 100% in "what", and now 100% on "how"
as well.

An implemented published method in a concrete class is as much part of a
contractual interface as a method signature in a Java interface.

>> What we're really arguing about here is whether it's desirable to bind
>> client code to provider contracts. It's clear that Map cannot enforce a
>> behavioural contract, and that LinkedHashMap does. Rather than beat that
>> to death, let's acknowledge that we have one camp that argues that we
>> don't want to tie the caller to a behavioural provider contract, and
>> another camp (me) that says that sometimes you do want and need to do
>> this.
> 
> I think you are missing the fact that the client is _already_ tied to a 
> contract by calling getSortedMap() to get the map (since the contract of 
> getSortedMap() is "return a map implementation that provides such and such 
> iteration order".
> The question is rather - do we need to specify this contract as a Java type?
> I would rather say: since the compiler cannot enforce/check the contract 
> anyway then it is useless - the contract specified as documentation of 
> getSortedMap() is enough.
> 
I agree that the compiler cannot enforce the contract unless both the
provider of the LinkedHashMap and the calling code are written
cooperatively to use LinkedHashMap explicitly, thereby locking in the
requirement. This is the scenario I've been positing.

As I believe I mentioned in another post, you could get away with
documentation, but I believe you'd have to document not just the method,
but also all the call sites. If you're going to rely on documentation
then perhaps your biggest win would be to change the name of the method
- getMap() would be an atrocious choice. IMO the only defensible choice is

Map getPredictableIterationOrderMap()

Now *this* stands out when you're using it.

AHS

[toc] | [prev] | [next] | [standalone]


#3913

FromMichal Kleczek <kleku75@gmail.com>
Date2011-05-10 15:51 +0200
Message-ID<iqbfs5$3u7$1@news.onet.pl>
In reply to#3879
Arved Sandstrom wrote:

> On 11-05-09 06:04 AM, Michal Kleczek wrote:
>> I think you are missing the fact that the client is _already_ tied to a
>> contract by calling getSortedMap() to get the map (since the contract of
>> getSortedMap() is "return a map implementation that provides such and
>> such iteration order".
>> The question is rather - do we need to specify this contract as a Java
>> type? I would rather say: since the compiler cannot enforce/check the
>> contract anyway then it is useless - the contract specified as
>> documentation of getSortedMap() is enough.
>> 
> I agree that the compiler cannot enforce the contract unless both the
> provider of the LinkedHashMap and the calling code are written
> cooperatively to use LinkedHashMap explicitly, thereby locking in the
> requirement. This is the scenario I've been positing.
> 
> As I believe I mentioned in another post, you could get away with
> documentation, but I believe you'd have to document not just the method,
> but also all the call sites. If you're going to rely on documentation
> then perhaps your biggest win would be to change the name of the method
> - getMap() would be an atrocious choice. IMO the only defensible choice is
> 
> Map getPredictableIterationOrderMap()
> 
> Now *this* stands out when you're using it.

Sure - naming of functions is one of the most important aspects of defining 
them.
Anyway.
Somehow I got lost in discussion and forgot the most important thing IMHO:
the fact that iteration order is important to the overall solution does not 
imply it is important to the client code. Take an example:

//the program is supposed to print hashcodes of strings provided as
//arguments in the order that the user gave them
//forget that the map is not needed here
public void PrintHashes {

  public static void main(String[] args) {
    final Map<String, Integer> mapOfHashes = new LinkedHashMap<>();
    calculateHashes(Arrays.asList(args), mapOfHashes);
    printMap(mapOfHashes, System.out);
  }

  private static <T> void calculateHashes(
    Iterable<? extends T> objects,
    Map<? super T, ? super Integer> hashes) {
    for (final Object object : objects) {
      hashes.put(object, object.hashCode());
    }
  }

  private static void printMap(Map<?, ?> map, PrintStream out) {
    for (final Map.Entry<?, ?> entry : map.entrySet()) {
      out.println("Key: " + entry.getKey() + " Value: " + entry.getValue());
    }
  }

}

According to your logic all references to Map<whatever> should be replaced 
by LinkedHashMap<String, Integer> which - sorry to say that - sounds insane 
:)

-- 
Michal

[toc] | [prev] | [next] | [standalone]


#3932

FromJim Janney <jjanney@shell.xmission.com>
Date2011-05-10 13:15 -0600
Message-ID<2p62pimko2.fsf@shell.xmission.com>
In reply to#3913
Michal Kleczek <kleku75@gmail.com> writes:

> Arved Sandstrom wrote:
>
>> On 11-05-09 06:04 AM, Michal Kleczek wrote:
>>> I think you are missing the fact that the client is _already_ tied to a
>>> contract by calling getSortedMap() to get the map (since the contract of
>>> getSortedMap() is "return a map implementation that provides such and
>>> such iteration order".
>>> The question is rather - do we need to specify this contract as a Java
>>> type? I would rather say: since the compiler cannot enforce/check the
>>> contract anyway then it is useless - the contract specified as
>>> documentation of getSortedMap() is enough.
>>> 
>> I agree that the compiler cannot enforce the contract unless both the
>> provider of the LinkedHashMap and the calling code are written
>> cooperatively to use LinkedHashMap explicitly, thereby locking in the
>> requirement. This is the scenario I've been positing.
>> 
>> As I believe I mentioned in another post, you could get away with
>> documentation, but I believe you'd have to document not just the method,
>> but also all the call sites. If you're going to rely on documentation
>> then perhaps your biggest win would be to change the name of the method
>> - getMap() would be an atrocious choice. IMO the only defensible choice is
>> 
>> Map getPredictableIterationOrderMap()
>> 
>> Now *this* stands out when you're using it.
>
> Sure - naming of functions is one of the most important aspects of defining 
> them.
> Anyway.
> Somehow I got lost in discussion and forgot the most important thing IMHO:
> the fact that iteration order is important to the overall solution does not 
> imply it is important to the client code. Take an example:

Agreed.  Neither does it imply that it is *not* important.  We don't
have enough information to determine that one way or the other.

-- 
Jim Janney

[toc] | [prev] | [next] | [standalone]


#3939

FromArved Sandstrom <asandstrom3minus1@eastlink.ca>
Date2011-05-10 19:40 -0300
Message-ID<K9jyp.25$RT2.19@newsfe02.iad>
In reply to#3913
On 11-05-10 10:51 AM, Michal Kleczek wrote:
> Arved Sandstrom wrote:
> 
>> On 11-05-09 06:04 AM, Michal Kleczek wrote:
>>> I think you are missing the fact that the client is _already_ tied to a
>>> contract by calling getSortedMap() to get the map (since the contract of
>>> getSortedMap() is "return a map implementation that provides such and
>>> such iteration order".
>>> The question is rather - do we need to specify this contract as a Java
>>> type? I would rather say: since the compiler cannot enforce/check the
>>> contract anyway then it is useless - the contract specified as
>>> documentation of getSortedMap() is enough.
>>>
>> I agree that the compiler cannot enforce the contract unless both the
>> provider of the LinkedHashMap and the calling code are written
>> cooperatively to use LinkedHashMap explicitly, thereby locking in the
>> requirement. This is the scenario I've been positing.
>>
>> As I believe I mentioned in another post, you could get away with
>> documentation, but I believe you'd have to document not just the method,
>> but also all the call sites. If you're going to rely on documentation
>> then perhaps your biggest win would be to change the name of the method
>> - getMap() would be an atrocious choice. IMO the only defensible choice is
>>
>> Map getPredictableIterationOrderMap()
>>
>> Now *this* stands out when you're using it.
> 
> Sure - naming of functions is one of the most important aspects of defining 
> them.
> Anyway.
> Somehow I got lost in discussion and forgot the most important thing IMHO:
> the fact that iteration order is important to the overall solution does not 
> imply it is important to the client code. Take an example:
> 
> //the program is supposed to print hashcodes of strings provided as
> //arguments in the order that the user gave them
> //forget that the map is not needed here
> public void PrintHashes {
> 
>   public static void main(String[] args) {
>     final Map<String, Integer> mapOfHashes = new LinkedHashMap<>();
>     calculateHashes(Arrays.asList(args), mapOfHashes);
>     printMap(mapOfHashes, System.out);
>   }
> 
>   private static <T> void calculateHashes(
>     Iterable<? extends T> objects,
>     Map<? super T, ? super Integer> hashes) {
>     for (final Object object : objects) {
>       hashes.put(object, object.hashCode());
>     }
>   }
> 
>   private static void printMap(Map<?, ?> map, PrintStream out) {
>     for (final Map.Entry<?, ?> entry : map.entrySet()) {
>       out.println("Key: " + entry.getKey() + " Value: " + entry.getValue());
>     }
>   }
> 
> }
> 
> According to your logic all references to Map<whatever> should be replaced 
> by LinkedHashMap<String, Integer> which - sorry to say that - sounds insane 
> :)

_That_ is not _my_ logic. My logic is that in the example provided by
the OP, there are sets of circumstances that make explicit use of
LinkedHashMap reasonable. These sets of circumstances may include both
the providing and calling code being non-published (that is, both of
them are involved in implementation details), and also the desire of the
designer/implementer to absolutely lock in this choice of Map
implementation in that non-published code.

Fact is, we don't know how public/published the OP intends that
map-producing method to be. Since we don't know, I've repeatedly tried
to more clearly explain the specific circumstances where I believe that
not using Map won't offend against the "program to the interface"
religion. I'm getting that there is quite a large group out there that
doesn't countenance *ever* breaking "program to the interface". So be it.

AHS

[toc] | [prev] | [standalone]


Page 4 of 4 — ← Prev page 1 2 3 [4]

Back to top | Article view | comp.lang.java.programmer


csiph-web