Monday, December 04, 2006

Serialization and the Collections API

I've put a little article up on my site. Its just a discourse on how some some best practices can come into conflict when using libraries, in this case the Collections API.
Its nothing against the Collections API but, food for thought when writing library code so that you can give consumers a helping hand.

permalink
Links to this post

9 Comments:

At 05 December, 2006 10:09, Anonymous Anonymous said...

A general comment:

public void setData(List list){
this.myList = list; // compiler error
}

"We don't want to restrict users of the class to specific implementations" --> right. but explain what does work.. people who see code that does not compile get confused.. explain WHY it does not compile and what can be done.

There are some typos which make the article look less than professional in my opinion:

Quite a few instances of its need to become it's (if the sentence can be read with "it is", it should read "it's", otherwise "its" is fine).

should declare is as a List --> should declare it as a List

puprpose -- >purpose

All in all - a very good effort, very interesting and informative.

 
At 05 December, 2006 10:28, Blogger willCode4Beer said...

Thanks, I've made some edits based on your recomendation

 
At 05 December, 2006 10:31, Anonymous Anonymous said...

Your article would be better if it more clearly stated the issue you are trying to solve, rather than assuming that "we all know what best practice is."

You don't have to explain in detail, just a link to a page like http://www.javapractices.com/Topic26.cjp would be helpful. Also, I would restate your rule to clarify that you are talking about preferring to declare variables as Interfaces rather than Classes.

I think that you also need to discuss WHY this is a best practice. This is essential to evaluating potential workarounds.

According to the page I linked, the recommendation seeks to avoid ripple effects in code if implementations change.

It seems to me that since your List is private within your class and since you use List when declaring the parameters to your set data function, you are limiting exposure to this risk to the code that implements YOUR class.

So, I think that you mention that it would be possible for you to serialize a List by writing your own implementation, but I suspect that you have not suggested this because the code involved would be more than the code that might need to change in the unlikely event that Arraylist changes.

You might also point out that you can further protect yourself from the risk of change by being careful to use only the List interfaces. To get compiler support for this, you could declare a private List reference to the actual ArrayList that is used within the your class implementation.

while it might make sense in terms of your actual class implementation to create an Array list in the constructor and then replace it with a new array when setting data, I'd initialize it to null in this context.

Grammar issue: You consistently leave out the apostrophe in it's (as in "it is").

 
At 05 December, 2006 12:09, Anonymous Anonymous said...

It looks like it would be useful for my website. The article sort of help me to integrate some features better, thank you

 
At 05 December, 2006 13:52, Anonymous Anonymous said...

I'm first and foremost a c++ programmer, generally just write my own serialization routines for everything.
This helps my limited Java ability.

 
At 05 December, 2006 15:03, Anonymous Jen said...

It's not clear to me why these things won't work together. If I trust you that they won't, the rest of your article very clearly goes about how to fix it. However, why does this code violate the second rule?

public class MySerObj implements Serializable {
static final long serialVersionUID = -1;
private List myList;
public MySerObj(){
myList = new ArrayList();
}
}


If the rule is that every field of a serializable class must be either serializable or transient, I'm unclear on what is not serializable or transient. List is serializable. ArrayList is serializable. I'm guessing it has to do with ArrayList implementing List, but I can't quite put my finger on it.

On one hand I'm not a professional programmer. On the other hand, I'm a computer scientist and wrote code through my dissertation in Java. I love these kinds of articles, and I would really appreciate this one more if you could add a few sentences explaining exactly why your code example I pasted above won't work.

Otherwise, very nice :)

 
At 05 December, 2006 15:05, Anonymous Anonymous said...

Hi. Based on over 35 years in scientific research and 20 in supercomputers, I have come to believe that Best Practices, while they have their place in this universe, when pushed too far simply inform us of their limitations, whether these show up in confusion, capability, or inefficiency. I believe that you have avoided any practical concern for the functionality of your software by maintaining a Protected Copy - this is a trick I use myself....

 
At 05 December, 2006 15:28, Blogger willCode4Beer said...

Jen, actually, the List interface doesn't extend the serializable interface, thus the issue.
http://java.sun.com/j2se/1.4.2/docs/api/java/util/List.html

The code you posted will absolutely work, because ArrayList does implement the Serializable interface :)

I know the example I posted is trivial and maybe List isn't the best example since, all of the imeplementations in the standard API do implement Serializable.
The worry is that in a large class, a maintainer may not realize that a class field should be serializable if its not initially declared as a serializable type.

Then again, as the last poster pointed out, sometimes worrying about it too much can just be overkill. I still think the discussion is useful though.

 
At 19 December, 2009 11:12, OpenID twic said...

You can abuse generics to get some way in the direction of something that looks a bit like a solution, and doesn't involve the cardinal sin of hardcoding an implementation type in your variable declaration:

@SuppressWarnings("serial")
class MySerObj implements Serializable {

private SerializableListHolder myListHolder;

public MySerObj() {
setMyList(new ArrayList());
}

public void setMyList(T newList) {
myListHolder = SerializableListHolder.newInstance(newList);
}

public List getMyList() {
return myListHolder.value;
}

}

@SuppressWarnings("serial")
class SerializableListHolder implements Serializable {

public static SerializableListHolder newInstance(T value) {
return new SerializableListHolder(value);
}

public final T value;

private SerializableListHolder(T value) {
this.value = value;
}

}

How's that?

 

Post a Comment

Subscribe to Post Comments [Atom]

<< Home

Links to this post on:

Create link here by posting on Blogger