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