Groups | Search | Server Info | Keyboard shortcuts | Login | Register


Groups > comp.lang.java.programmer > #3699

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

From Daniele Futtorovic <da.futt.news@laposte-dot-net.invalid>
Newsgroups comp.lang.java.programmer
Subject Re: "Program to an interface" - When to break a design pattern
Date 2011-05-06 18:56 +0200
Organization A noiseless patient Spider
Message-ID <iq1973$i3r$1@dont-email.me> (permalink)
References (5 earlier) <2pk4e4q2sq.fsf@shell.xmission.com> <ipv6q5$vq4$1@dont-email.me> <SPFwp.15920$rB2.9262@newsfe21.iad> <ipvfbo$o57$1@dont-email.me> <P%Pwp.14014$ei6.7822@newsfe19.iad>

Show all headers | View raw


On 06/05/2011 12:24, Arved Sandstrom allegedly wrote:
> On 11-05-05 09:28 PM, Daniele Futtorovic wrote:
>> On 06/05/2011 00:49, Arved Sandstrom allegedly wrote:
>>> On 11-05-05 07:02 PM, Daniele Futtorovic wrote:
>>>> On 05/05/2011 23:02, Jim Janney allegedly wrote:
>>>>> Daniele Futtorovic<da.futt.news@laposte-dot-net.invalid>    writes:
>>>>>
>>>>>> On 05/05/2011 22:42, Jim Janney allegedly wrote:
>>>>>>> Daniele Futtorovic<da.futt.news@laposte-dot-net.invalid>     writes:
>>>>>>>
>>>>>>>> On 05/05/2011 22:14, Jim Janney allegedly wrote:
>>>>>>>>> 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.  So
>>>>>>>>> in this case, no, programming to the interface would be the wrong
>>>>>>>>> thing to do.  The point of design principles is to make you think
>>>>>>>>> before you break them :-)
>>>>>>>>
>>>>>>>> Entirely disagreed. The code shown did not contain any
>>>>>>>> justification for
>>>>>>>> breaking the pattern in question, and on the opposite, it contained
>>>>>>>> all
>>>>>>>> the reasons to think more about encapsulation, which is the true
>>>>>>>> underlying rationale for coding to interfaces -- not polymorphism
>>>>>>>> per se.
>>>>>>>
>>>>>>> The justification is not in the code shown, but in the accompanying
>>>>>>> remark "I need the map to retain the insertion order."  There's no
>>>>>>> interface in the JRE that promises this, and only one class that
>>>>>>> provides it, which makes encapsulation, shall we say, difficult.
>>>>>>
>>>>>> That's not the point! Yes, you need a LinkedHashMap to retain
>>>>>> insertion order in a Map. But retaining insertion order is
>>>>>> relevant... only when inserting.
>>>>>
>>>>> Think a minute.  When does retaining insertion order actually matter?
>>>>> When you build the map, or some time later when you iterate over it?
>>>>> Hint: if you never iterate over it, the order doesn't matter at all.
>>>>
>>>> I don't need a full minute to see that this is even further beside the
>>>> point.
>>>
>>> Yeah, as in, your argument is incorrect, and Jim is right.
>>>
>>> You see this bit from the LinkedHashMap API?:
>>>
>>> "This implementation spares its clients from the unspecified, generally
>>> chaotic ordering provided by HashMap (and Hashtable), without incurring
>>> the increased cost associated with TreeMap. It can be used to produce a
>>> copy of a map that has the same order as the original, regardless of the
>>> original map's implementation."
>>>
>>> "Spares its _clients_". You provide this implementation for the
>>> _clients_. Just any Map won't do, Daniele. And if you "program to the
>>> interface" blindly, and return a Map from this method, then as long as
>>> the OP's _unchanged_ code is used to implement
>>>
>>> public Map<String, Integer>   getSortedMap()
>>>
>>> then we'll get a LinkedHashMap and obey the desired contract. But down
>>> the road - since we've failed to specify the requirement - things could
>>> change, and the original implementation requirement be violated. In fact
>>> a maintainer will look at the method's return type, and the
>>> (unfortunate) name of te method, and in the absence of design
>>> documentation decide maybe to use a SortedMap implementation instead.
>>> *Which would be a mistake*...but your recommended approach would
>>> encourage him to do it.
>>>
>>> Don't get all blinded by design principles like "program to the
>>> interface". Most of the things you access in a real-world complex
>>> application are exposed through classes, not interfaces.
>>
>> I can't say I take too kindly to your assertion that I intervened as I
>> did for the sake of blindly following anything.
>
> OK, I'll retract the word "blind". I see you arguing strenuously for the
> use of Map, and in this case I believe you're wrong. How's that?

Fair enough. :)

Although if I were to nitpick, I don't think I'm strenuous about it. I'm 
simply convinced that I am right, and all experience I can currently 
summon backs that.

>> Neither do I agree with your interpretation of the bit of Javadoc you
>> quoted. No, you do not provide a LinkedHashMap to clients. You provide a
>> Map with the same iteration order as another. Nuance.
>
> It's not about providing a Map with the same iteration order as
> "another". There might be no "other". In the case of a stock
> LinkedHashMap we know that the predictable iteration order is insertion
> order. But mainly the contract we're after is predictable iteration
> order, regardless of how the map was loaded. That is what the Javadoc says.

True, there might be no other: the Map may have been constructed and 
filled in the method itself.

But I maintain that the iteration order of a LinkedHashMap is *not 
predictable*, *unless* you know the order in which elements were 
inserted in it (or can make reasonable assumptions as to that).


> As far as your nuance is concerned, I'm interested (the _OP_ is
> interested) in providing a map with predictable insertion order. Map
> does not satisfy that; LinkedHashMap does. If I return Map then I am
> making a mistake.
>
>> The return type being a LinkedHashMap, itself, doesn't tell you
>> _anything_ about its iteration order.
>
> ??? It tells me that it has a predictable iteration order (which happens
> to be insertion order). It's the _predictable_ bit that is important.
> That it happens to be insertion order is a bonus but not the key point.

I repeat: the iteration order is *not predictable* if you don't happen 
to know the insertion order (unlike e.g. a SortedMap).


>> Take the following code:
>>
>> ################################################
>> interface Function<K, V>  {
>>    V f( K k );
>> }
>>
>> static<T>  LinkedHashMap<T, V>  map( Map<T, U>  input, Function f ){
>>    Map<T, V>  ret = new HashMap<T, V>();
>>    for( Map.Entry<T, U>  entry: input.entrySet() ){
>>      ret.put( entry.getKey(), f.f( entry.getValue() ) );
>>    }
>>    return new LinkedHashMap<T, V>( ret );
>> }
>>
>> Q: What does the return type tell you about the iteration order of the
>> returned instance?
>> ################################################
>>
>> Like it or not, only the method's *contract*, if anything, can guarantee
>> you that the returned instance will iterate in the same order as the input.
>
> Input? Did you see the OP's method signature? Why not stick to that? As
> it happens _your_ method does something different: it takes its input,
> preprocesses it, and _only then_ does anything with LinkedHashMap.
> Ironically the
>
> return new LinkedHashMap<T, V>( ret );
>
> retains the insertion order of the "ret" pre-processed map, and does
> what LinkedHashMap is supposed to do.
>
> All that fancy cruft you have prior is irrelevant and belongs in your
> concocted method...which is not the original method signature. If you're
> going to highlight method contracts, kindly use the same one as is being
> discussed.

I know this is not the same code as the OP. But I think it proves that 
the return type of a method being LinkedHashMap does not necessarily 
tell you anything about the iteration order of that method's return value.

As I mentioned in reply to Jim yesterday, there is only one case I can 
think of where it would be justifiable to make the return type 
LinkedHashMap: if it's a factory method (the OP's code is not sufficient 
to confirm or infirm that).

But even then I question the need for the caller to know that it's a 
LinkedHashMap. The only (borderline) case where it would be relevant 
would be something like this:

public class SomeClass<U, V> {

   LinkedHashMap<U, V> createNewMap(){ ... }

   V resolve( U u ){ ... }

   static boolean eq( Object o1, Object o2 ){
     return o1 == null ? o2 == null : o1.equals(o2);
   }

   public LinkedHashMap<U, V> doSomething( Collection<U> c ){
     LinkedHashMap<U, V> map = createNewMap();
     for( U u: c ) map.put( u, resolve(u) );

     Iterator<U> it1 = c.iterator(), it2 = map.keySet().iterator();
     for( ; it1.hasNext(); assert eq( it1.next(), it2.next() ) );
     assert ! it2.hasNext();

     return map;
   }

In this case, I would be guaranteed that #doSomething() never throws an 
AssertionError or a NoSuchElementException. Cool. But borderline. And if 
the assertion were done *elsewhere* than in the very method that does 
the insertion, then #doSomething()'s return type being LinkedHashMap 
would not tell you *anything* as to whether or not the assertion holds.

Please provide a code example that contradicts this.

-- 
DF.
An escaped convict once said to me:
"Alcatraz is the place to be"

Back to comp.lang.java.programmer | Previous | NextPrevious in thread | Next in thread | Find similar


Thread

"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

csiph-web