tags:

views:

103

answers:

6

I haven’t done much Java programming and hence a lot of unanswered ORM questions revolve in my head that might seem as fairly straight forward to more seasoned folks.

Let's say we have two classes: Customer and Order. Customer class implements a method called listAllOrders, what should the method’s signature be?

  1. Set<Order> getAllOrders(); // the OOP way

  2. Set<Integer> getAllOrders(); // db-friendly way, based on the assumption that each order is assigned a unique int id

  3. int[] getAllOrders(); // db-friendly way, optimised

  4. Set<OrderID> getAllOrders(); // the OOP way, optimised

  5. Other? A combination of the above through method overloading?

My thinking is to dismiss 3rd option right away, since the optimisation is premature, uncalled for and is likely to cause more trouble than good.

Choosing between the 1st and the 2nd options, the main argument seems to be that in many scenarios returning a collection of orders instead of id’s is going to be an overkill.

The 1st option would always require pre-loading of orders into memory and although some order properties can be handled through lazy loading the Order objects themselves would still require significantly more memory allocated as opposed to a set of bare id’s. The other reason seems to be that lazy loading won’t give me the advantage of using the final modifier to enforce immutability of Order fields.

However, option 2 doesn’t really encapsulate order numbering, i.e. if it were decided to start using String UUID or long as order identifier instead of integer it would become necessary to do a serious rewrite. Obviously this could be mitigated by introduction of a new lightweight object called OrderId (4th approach).

Well, at this point I'd really appreciate some help from ORM and Java gurus!

+4  A: 

It always helps to know what the caller wants. It isn't an optimization to return an order id if every time, the caller is then going to have to look up every single order. On the other hand, if most of the time they don't need all that information, then there isn't any point in return it.

I would go for option 1 most of the time. But if it's something memory constrained like a smart phone, I think I'd go for the lazy expansion.

Paul Tomblin
+1  A: 

I suggest to use option one, because you are dealing with business objects and not messing with numbers. If you need the id, you can still obtain it from an order. And if you use a smart OR mapper, only the primary key of an order will be loaded until you access some real data - so no point to wory about database or memory performance.

Daniel Brückner
A: 

I have to agree with Paul Tomblin, if the function is called getAllOrders() I would expect it to return an order object (assuming such a class exists). The function should be called getAllOrderIds() if its going to return something more specific.

Soviut
A: 

Option #2 is, like option #3, a premature optimization. Your client wants to know what the orders are; it may very well not even care what the orders' IDs are. There are circumstances where a client might want the IDs, but if you see that happening, you should probably ask Why? and find a way to operate directly on the Orders themselves.

Carl Manaster
A: 

I'll echo Paul Tomblin in saying that the question is not, "What's the best thing to do?" but "What's the best way to accomplish this objective?" Before you can say what the return value of a function should be, you have to decide what the caller is going to do with the information. If what the caller wants to do is, say, display a list of Order IDs for the user, then return Order IDs. If the caller wants to display a list of order dates, total cost, and shipment statuses, then I'd return a set of objects containing that data. Etc.

+2  A: 

One of the hardest things for people that are new to ORM tools is that they try to apply the knowledge they have of the DB and the optimizations that were used in that context (storing IDs, etc.). I would suggest that you work with objects, and address performance problems if they come up.

Most ORMs handle this type of concern for you; Hibernate for example will by default lazy-load a collection (or Orders in your case). Internally it will store a collection of the ID values for you, but this is really not your concern as you will only interact with the object and collection of associated objects. If you focus on your domain objects and think "OO", your ORM tool should support you and allow you to further optimize later if it becomes necessary.

Rich Kroll