Fog Creek Software
Discussion Board




OO: Lists, Collections, and Objects

Quick poll for java programmers and OO architects:

Given an application that frequently uses a collection of objects -- such as 1..n Invoice(s) -- should the collection be modelled as (a) or (b)...

(a) An object implementing the List interface, such as "Invoices", with convenient accessors such as
  public Invoice get(int i);

(b) A plain-old List (let the everyone get and cast as needed).

(c) Get back to work!

Caffeinated
Monday, May 24, 2004

In C++ you don't need to ask: because you can so easily use a template, to get strong typing.

In C# (which doesn't have templates, so that I need to write LOC to implement (a)), I find myself using (b) for "private" data and for "internal" interfaces, and using (a) for "public" interfaces (i.e. for interfaces where I especially want to document and/or enforce how the interface is used by other programmers).

Christopher Wells
Monday, May 24, 2004


a

Gen'xer
Monday, May 24, 2004

Definitely (a)!

anon
Monday, May 24, 2004

b

Even better, use List<Invoice>, either with java 1.5 or with a 1.5 compiler generating 1.4 (or previous) compatible sources.

Even if you can't use parameterized types, I like declaring list-returning functions like this:
    public List /* <Invoice> */ getInvoices();
    public void processInvoices(List /* <Invoice> */ invoices);

It's just a documentation convention, but it's useful.

schmoe
Monday, May 24, 2004

Do you really think for every type you will have
the perseverance to create a new list type
and then have all those list types work alike?

Consider over time you'll add higher level methods
to operate on the list. So maybe consider the
"list" a more generic container and divorce it
from its listness from the start.

son of parnas
Monday, May 24, 2004

(d) Whichever is easiest.

Crimson
Monday, May 24, 2004

Perhaps (d) Wait for Java 1.5 and generics, using (b) as a stopgap? ;)
http://java.sun.com/j2se/1.5/pdf/generics-tutorial.pdf

I haven't actually read that link, but it seems to have stuff about how it plays well with legacy code.

Tayssir John Gabbour
Monday, May 24, 2004

>> "Do you really think for every type you will have the perseverance to create a new list type and then have all those list types work alike?"

Ummm... Yes.  How much work is it?!?  Jeez.  And, BTW, what do you think the Java collections framework is for?

anon
Monday, May 24, 2004

Use Python and let it do the typing for you dynamically.

Tom H
Monday, May 24, 2004

>Ummm... Yes.  How much work is it?!? 

Enough that people won't do it properly.

>And, BTW, what do you think the Java collections framework is for?

Hm, no options?

anoymous
Monday, May 24, 2004

First, the subject of the tread is misleading. It should be like "How to deal with Java deficiencies while dealing with Lists, ..."

Second, the option (a) doesn't make much sense. You're going to implement the List interface, right? So, you will implement methods like add(Object o), contains(Object o) or Object get(int index). Note: the interface still wors with Objects, so you will not get compile-time checking, only the runtime. Why bother re-implementing List, then? You will get the runtime errors in any case.

Of course, you can forget the List interface completely and implement a completely new class, having methods like add(Invoice) and Invoice get(int)... But that is reimplementing the wheel. A new container interface for each new object? It doesn't scale, by many reasons.

My recommendations:

- Given the current Java limitations, choose (b).

- If casting and the runtime errors seriously bother you, choose the better language. For example, C++  allows type-safe containers. OTOH, Ruby/Python are pure OO languages, that don't have this problem at all.

igrek
Monday, May 24, 2004

Use a plain-old List, unless you really have a need for some non-List operations. Otherwise you'll have to deal with the hassle of implementing the 3 dozen methods of the List interface (even though you could make them pass-through to a private List, it's still a pain).

And if you do use a List, make sure that any public method that returns the List will have a return type of List or Collection and not a concrete instance like ArrayList.  That way, if you want to in the future you can more easily enhance it to return your own hand-rolled InvoiceList or anything else that implements the List interface.

T. Norman
Monday, May 24, 2004

I'll just echo what the last post said. Most of the time, you can use the standard Java collections. Creating your own collection class makes sense when you need a method, like addAllUnpaidInvoices(), that acts on the collection, in that case I'd extend an existing collection class.

Julian
Tuesday, May 25, 2004

How about:

public class InvoiceList extends LinkedList {
  public Invoice getInvoice (int i){ return (LinkedList)this.get(i);}
}

After all, OO is all about code reuse, isn't it?

  -tim

a2800276
Tuesday, May 25, 2004

Caffeinated, you should go d):

d) create an InvoiceArchive with a getInvoice method. So neither Invoice nor the other classes need to know how Invoices are stored.

Giovanni Corriga
Tuesday, May 25, 2004

With C#, I use CodeSmith to generate strongly typed collections. Is there a Java equivalent that can generate classes from template definitions?

Chris Nahr
Tuesday, May 25, 2004

*  Recent Topics

*  Fog Creek Home