Hi Stefano,

Java 5:  I like the language features of Java 5.  It's not a hard requirement, 
but things like enums fit well with my intended design.  I even considered 
making Java 6 a requirement because it has built-in support for IDN and that 
wouldn't have to be built into the library.  I've compromised though and if 
using Java 6 IDN will be supported, but on Java 5 or below it isn't.  Later I 
could re-implement the IDN suppport so it is available on Java 5 as well.  But, 
as time progresses, support for older JVM's becomes less necessary.  That's why 
I selected Java 5.  Yes, some people are still building apps for older JVM's, 
but there are fewer every day.  And if someone absolutely had to support < 1.5, 
dnsjava is available.

Record mutability:  My desire for mutable records is not performance.  It's 
ease of development for a specific class of applications.  For a cache, 
immutable records make sense.  For a GUI application that manages DNS, it's a 
royal pain.  But, my design allows for both.  As I said in my original post "I 
want mutable objects, that can be selectively made immutable".   I intend to 
create an aspect (using AspectJ) that would add the method .setImmutable() to 
Record and any object extending Record.  Once that method is invoked any call 
to setXXX(..) would throw an ImmutableObjectException.  So now you have mutable 
and immutable objects in one library and can select which usage pattern is most 
appropriate for the application you are developing.

This leads to an added benefit of Java 5.  There could be methods that don't 
follow the setXXX(..) pattern but would modify a record's data.  With Java 5 I 
can create an annotation "@SelectivelyImmutable" and simply annotate any method 
that shouldn't be invokable on an immutable object.

In addition to support for immutability, AspectJ provides other features too.  
When building a GUI application and using an ORM it's good design to have an 
artificial key for object identity.  At the same time, it doesn't make sense to 
have this extra field taking up space in your cache of immutable records when 
your not using an ORM.  With AspectJ, I can add the artificial object identity 
field to the record for use in the GUI application, but leave it out of the 
Record object for more efficient cache space usage.

I've put a lot of thought into small performance trade-offs like the above.  
For example, a number of operations might need the wire-format of a record.  
You could cache the wire-format of the record or re-create it every time.  The 
initial reaction of most developers would be to cache the wire-formated data 
because this is faster.  It IS faster, but not a lot faster.  It only takes 
microseconds to recreate the wire format on any modern processor.  The downside 
of caching the wire-formatted bytes are 1) you will double the in-memory 
footprint of your object, 2) you will need to invalidate the cached value if 
any data in your object changes.

You might call operations which need the wire-format of a record 4-5 times 
during the processing of a single request.  That might add a few milliseconds 
to the processing time.  But by doubling your objects memory footprint you will 
only be able to store half as many objects in your cache.  Is it worth trading 
1/100 th of a second worth of CPU time per request to double, triple, or 
exponentially improve your cache hit rate?  Probably.  Plus it greatly 
simplifies the library logic because there is no cached wire-format to be 
tracked/purged when the data changes on mutable objects.

Oh, and my design uses all runtime exceptions too.  This greatly
simplifies development because I've found error handling is usually
located in only one or two places "up the stack".  Using
RuntimeExceptions eliminates the need to liter my code with what
eventually becomes meaningless exception declarations.  I still Javadoc
the important exceptions that could be thrown by a method though.  This does 
require more diligence by the user of the library, but I've found it to be a 
much better solution than checked exceptions.

Rob


----- Original Message ----
From: Stefano Bagnara <[EMAIL PROTECTED]>
To: dev@mina.apache.org
Sent: Friday, June 22, 2007 6:06:33 AM
Subject: Re: DNS Protocol (Was: DHCP Protocol Home)

Hi Rob,

this is a great report! I think it will be very useful when we'll define
our goals and how to proceed.

I agree on almost all of your concern. Let's track down some
incompatibility between your view and other's people opinions I read in
this DNS thread.

Java 5: is this a big requirement for you? Personally I have no big
requirement for platform and I would be fine with a java5+ library, but
I think many users out there have 1.4 compatibility as a requirement.

Record mutability: how often do you need this? Have you compared real
performace tradeoff between mutable records and "immutable
records+clone" approach? I think that when the records are used by
multiple threads then immutability have a great impact on performance.
(e.g: if you return an immutable object from the cache then the user can
read it and do whatever he wants, otherwise you cannot ever return to
the user a record from the cache)

Thank you,
Stefano

PS: it would be really cool to have a "preview" of your code, even if it
is far from be complete.

Rob Butler ha scritto:
> Having worked with dnsjava, I felt there were some significant issues with it 
> for the types of applications I wanted to develop.
> 
> Specifically, 
> 
> * I want mutable objects, that can be selectively made immutable.
>     - dnsjava records are always immutable.
> 
> * I want my objects to always work the same no matter if a message has been 
> "built"/marshaled/unmarshaled.
>     - some methods, specifically on the Message object behave differently if 
> you are working with a message that has been parsed from the wire VS one your 
> are building programatically.  For example, if you call Message.setTsig(..) 
> and later call Message.getTsig() you would expect to get back the TSIG you 
> set previously.  With dnsjava you only get a TSIG back from getTsig() if the 
> message was parsed from the wire.
> 
> * I want all overloaded messages to behave similarly, as a Java coder would 
> expect.
>     - Message.toWire() and Message.toWire(int) in dnsjava have some 
> differences in how they behave.  For example, if you had called 
> Message.setTsig(..) you would expect the TSIG to be written in the DNS 
> message when calling .toWire() or .toWire(int).  The TSIG is only written 
> when .toWire(int) is called.
> 
> * I wanted a better OO design and I wanted to use Java 5 language features.
>     - a DNS Header as a separate object doesn't really make a lot of sense to 
> me.  It only has worth as part of a message.  It should at best be an inner 
> class that is not directly exposed as an object outside of Message, if such a 
> class even exits.  All operations that are in dnsjava's Header should be on a 
> Message object.
>     - Because Header is a separate object from Message, it is possible for 
> strange things to happen in dnsjava.  For example, your header could say 
> there are 2 records in the answer section, even though there are none or vice 
> versa.
>     - There are response codes for messages, TSIGRecords, and a few other 
> record types.  Even though the response code for NOERROR is always the same 
> value, the various response codes should probably be inner enums of the 
> appropriate object types.  It wouldn't make sense to specify an NXDOMAIN 
> response code for a TSIGRecord, but with dnsjava you can.
>     - Data class only makes sense on records.  There should probably be an 
> inner enum on Record that defines what they are instead of it being a 
> separate class.
>     - dnsjava doesn't track some data that it should.  For example, if you 
> parse a message off the wire, you should be able to do something like 
> TSIG.verify(incomingMessage), because the incomingMessage should know what 
> the bytes were on the wire.  dnsJava doesn't keep track of the original 
> bytes, so you have to.  Because of details I won't get into it's necessary to 
> track the original message bytes for TSIG validation.  You cannot simply 
> re-construct the byte stream by calling Message.toWire().
> 
> * I wanted more separation between a DNS parsing library and things built 
> with it.
>     - For example, dnsjava includes a resolver and a minimal DNS server along 
> with all of the parsing code.  It's great this is supplied as part of the 
> project, but they should be separate modules (jars) within the project.  If 
> your building a DNS server using dnsjava there is no reason to have dnsjava's 
> server and resolver present.  It's not a big deal that they are, but i feel 
> they should be separate.
>     - I wanted the parsing library as separate from the IO implementation as 
> possible.
> 
> * I wanted a better exception hierarchy that would allow a developer to know 
> exactly what went wrong instead of just a single exception for all errors.
> 
> * I wanted support for evolving standards like NSEC3, IDN, etc.
> 
> * I wanted to do everything possible to make it as fast as possible w/o 
> trading off good design.
> 
> * I wanted everything fully javadoc'd.
> 
> Considering all the above, and more, I thought starting from scratch would be 
> the best approach.  I don't want this to sound like a dnsjava bash fest 
> though.  Brian's done some great work developing dnsjava and making it open 
> source.  I've learned a lot from using it and reviewing it's code.  I'd just 
> like to develop something with a better "Java feel".  Consider it dnsjava 2.0.
> 
> Rob











       
____________________________________________________________________________________
Take the Internet to Go: Yahoo!Go puts the Internet in your pocket: mail, news, 
photos & more. 
http://mobile.yahoo.com/go?refer=1GNXIC

Reply via email to