On 14 August 2011 15:47, Gary Gregory <garydgreg...@gmail.com> wrote: > On Sat, Aug 13, 2011 at 10:02 PM, sebb <seb...@gmail.com> wrote: >> On 12 August 2011 20:56, Gary Gregory <garydgreg...@gmail.com> wrote: >>> Hello All: >>> >>> For a first cut at generics support in Codec, please checkout the >>> branch >>> https://svn.apache.org/repos/asf/commons/proper/codec/branches/generics >>> >>> I wrote a migration guide in the root of the project called >>> Codec2-Migration.htm. >>> >>> Let's discuss. >> >> The original code used Encoder and Decoder interfaces which operated >> on Object, and extended these with >> BinaryEncoder (byte[]) >> StringEncoder(String) >> >> So for example StringEncoder classes need to implement >> encode(Object) : Object >> encode(String) : String >> >> As far as I can tell, those interfaces cannot be directly generified, >> because type erasure causes a method signature clash. >> So adding generics here means breaking binary compatibilty. > > Hello Sebb, > > Thank you for taking the time to look this over. > > You are correct, a class cannot implement an interface twice, so it > cannot implement the generics version of StringEncoder AND > BinaryEncoder. > >> >> Question is, what does adding generics to these interfaces actually provide? > > As you know. generics let us define precisely what types are supported > and avoids the current bug prone guessing game for implementers and > call sites.
Generics is one way to do this; it's not the only way. As I see it, the problem with the current Encoder/Decoder interface is that it allows Object. The sub-interfaces are specific, so are not a problem. > For example, look at the current mess in trunk's BinaryCodec: > > If I call encode(byte[]), I get a byte[] back. > > If I call encode(Object) with a byte[], I get a char[] back. > > Uh? Is the code wrong, is the Javadoc wrong, how am I supposed to know > what is right? I say it's a mess. > > I would flip the question around: If I implemented this today (1) why > would I not use generics, and (2) why would I want to support "Object > encode(Object)". Codec 2.0 is the opportunity to clean this up. What I > write about Encoders here applies to Decoders too. > > Most encode/decode methods look like this: > > public Object encode(Object raw) throws EncoderException { > if (!(raw instanceof byte[])) { > throw new EncoderException("argument not a byte array"); > } > return toAsciiChars((byte[]) raw); > } > > There is always one (or more) if instanceof expr for a typed method > call, and codec-styled class cast exception in the form an > EncoderException.This does not smell OO to me. Agreed, it is messy. > Tangent: Wouldn't this be better typed as a ClassCastException or an > IllegalArgumentException anyway? > > Any advantage of this pattern (is there one? ;) is ruined by the foggy > example above. I say foggy and not black box because we are FOSS. > > I also want typed asymmetric encoders, for example, for the new BM > encoder, I want "Set<String> encode(String)", or "Set<CharSequence> > encode(CharSequence)" Then the problem becomes that a single class cannot implement multiple generic interfaces. As far as I can tell, to use generics here would require many more smaller classes. > Hex decoding is a similar but differently confusing example: > > If I call encode(byte[]), the result is: > > StringUtils.getBytesUnchecked(encodeHexString(array), getCharsetName()); > > encodeHexString(array) creates a string which encode(byte[]) uses with > getBytesUnchecked and the char set name. So encodeHexString(array) > calls "new String(encodeHex(data))". > > If I call encode(Object) with a byte[], the result is: > > encodeHex(byteArray) > > Why the difference with the charset name? Do I want to spend the time > telling the difference? Is the code wrong? Is the Javadoc wrong? No idea. > The Hex decode(byte[]|Object) methods suffer from the same problem. > > Every encode/decode(Object) typed method creates duplication and > opportunities for bugs. > > So we have /at least/ three problems today with the current system > which I claim would be eliminated by using generics because there > would be one entry point for each type and it would get rid of > encode/decode(Object) methods. > >> Would it not be just as effective to deprecate Decoder and Encoder, >> and code can then use either BinaryEncoder or StringEncoder (etc)? > > We could do that too, but I would still want typed Decoder and Encoder > to define codecs that do not fit in BinaryEncoder or StringEncoder. > > For an example different from the new BM encoder, we could recode the > DoubleMetaphone encoder as DoubleMetaphoneResult<String, > DoubleMetaphoneResult>. I suggested using additional specific interfaces in a later e-mail. > Today, if you want both encodings (normal and alternate,) you have to > encode twice with a different parameter to encode(String, boolean) > which is not in any interface (and both values are computed internally > each time!) Granted, this problem could be solved without generics, > but generics makes it obvious what the result type is, instead of > reading possibly buggy Javadocs for a return typed as Object. Only > changing the result type in 2.0 of "Object encode(Object)" from String > to DoubleMetaphoneResult would be a runtime 'surprise' as opposed to a > compile time 'surprise.' Catching problems the earlier, the better > when migrating. Agreed. > Thank you for the discussion, :) > > Gary > >> >> At the moment test code is of the form: >> >> Encoder enc = new Base64(); >> ... >> byte [] ba = (byte[]) enc.encode(binary)); // unchecked cast >> >> However this could be written: >> >> BinaryEncoder enc = new Base64(); >> ... >> byte [] ba = enc.encode(binary)); // no cast needed >> >> >>> I plan on not touching trunk until the generics code is flushed out >>> and brought back to trunk. >>> >>> Thank you, >>> Gary >>> >>> -- >>> http://garygregory.wordpress.com/ >>> http://garygregory.com/ >>> http://people.apache.org/~ggregory/ >>> http://twitter.com/GaryGregory >>> >>> --------------------------------------------------------------------- >>> To unsubscribe, e-mail: dev-unsubscr...@commons.apache.org >>> For additional commands, e-mail: dev-h...@commons.apache.org >>> >>> >> >> --------------------------------------------------------------------- >> To unsubscribe, e-mail: dev-unsubscr...@commons.apache.org >> For additional commands, e-mail: dev-h...@commons.apache.org >> >> > > > > -- > Thank you, > Gary > > http://garygregory.wordpress.com/ > http://garygregory.com/ > http://people.apache.org/~ggregory/ > http://twitter.com/GaryGregory > > --------------------------------------------------------------------- > To unsubscribe, e-mail: dev-unsubscr...@commons.apache.org > For additional commands, e-mail: dev-h...@commons.apache.org > > --------------------------------------------------------------------- To unsubscribe, e-mail: dev-unsubscr...@commons.apache.org For additional commands, e-mail: dev-h...@commons.apache.org