开发者

Java = Return Object list/array vs. Result-Object (the same with method parameters)

This might seem to be a strange question: I am struggling to decide whether it is a good pra开发者_运维知识库ctice and "efficient" to work with "Typed Objects" on a very granular level.

public Object[] doSomething() {
    Object[] resultList = new Object[] {new Foo(), new Bar()};
    return resultList;
}

versus

public Result doSomething() {
    Result result = new Result();
    result.foo = new Foo();
    result.bar = new Bar();
    return result;
}

public class Result{
    Foo foo;
    Bar bar;
}

My question is concrete as follows:

  1. In terms of CPU Cycles (as a relative figure), how much does the second approach consume more resources. (like 100% more)

  2. The same question in regard to memory consumption

NB (these two are questions to understand it more, its not about premature optimization)

  1. In terms of "good design practice". Do you think version 1 is an absolute No-Go or do you rather think it actually does not matter...Or would you propose never returning "object Arrays" (((in an object oriented programming language)))...

This is something, I am always wondering if I should create dedicated Objects for everything (for passing values) or I should rather use generic objects (and common method parameters...)

The question also applies to

public doSomething(Query query ) 

versus

public doSomething(Foo foo, Bar bar, Aaaa, a, Bbbbb)

thanks

Markus


3.) In terms of "good design pratice". Do you think version 1 is an absolute No-Go or do you rather think it actually does not matter...Or would you propose never returnung "object Arrays" (((in an object oriented programming langauge/regarding encapsulation ...)))...

Version 1 is absolutely a no-go. It's almost completely untyped. The caller has to know the actual types and where they are in the array, and cast appropriately. You lose any useful compile-time type checking, and the code itself is significantly less clear.

I would never return an Object[] unless the values it contained were constructed with new Object().


I don't believe that defining a Result class and returning that consumes any more resources at run time than constructing an Object[]. (Granted, there's a miniscule cost for storing and loading the class definition.) Do you have data that indicate otherwise?

Returning an untyped object array is poor practice for various reasons, among which are:

  1. It's prone to error.
  2. It's harder to maintain.
  3. Casting back to the "real" type is not free, either.

Regarding your other query:

public doSomething(Query query) 

versus

public doSomething(Foo foo, Bar bar)

This is less clear-cut. If packaging up a Foo and a Bar into a Query object makes sense in the problem domain, then I would definitely do it. If it's just a packaging up for the sake of minimizing the number of arguments (that is, there's no "query object" concept in your problem domain), then I would probably not do it. If it's a question of run-time performance, then the answer is (as always) to profile.


I'd have to do an experiment to really know, but I'd guess that the object array would not be significantly faster. It might even be slower. After all, in either case you have to create an object: either the array object or the Result object. With the Result object you have to read the class definition from disk the first time you use it, and the class definition has to float around in memory, so there'd be some extra cost there. But with the array object you have to do casts when you pull the data out, and the JVM has to do bounds checkings on the array (What happens if the caller tries to retrieve resultList[12]?), which also involves extra work. My guess is that if you do it only once or twice, the array would be faster (because of the class load time), but if you do it many times, the dedicated object would be faster (because of the cast and array access time). But I admit I'm just guessing.

In any case, even if the array does have a slight performance edge, the loss in readability and maintainability of the code almost surely isn't worth it.

The absolute worst thing that can happen is if values you're returning in the array are of the same class but have different semantic meanings. Like suppose you did this:

public Object[] getCustomerData(int customerid)
{
  String customerName=... however you get it ...
  BigDecimal currentDue=...
  BigDecimal pastDue=...
  return new Object[] {customerName, pastDue, currentDue};
}
... meanwhile, back at the ranch ...
Object[] customerData=getCustomerData(customerid);
BigDecimal pastDue=(BigDecimal)customerData[2];
if (pastDue>0)
  sendNastyCollectionLetter();

Do you see the error? I retrieve entry #2 as pastDue when it's supposed to be #1. You could easily imagine this happenning if a programmer in a moment of thoughtlessness counted the fields starting from one instead of zero. Or in a long list if he miscounted and said #14 when it's really #15. As both have the same data type, this will compile and run just fine. But we'll be sending inappropriate collection letters to customers who are not over due. This would be very bad for customer relations.

Okay, maybe this is a bad example -- I just pulled it off the top of my head -- because we would be likely to catch that in testing. But what if the values we switched were rarely used, so that no one thought to include a test scenario for them. Or their effect was subtle, so that an error might slip through testing. For that matter, maybe you wouldn't catch this one in testing if you were rushing a change through, or if the tester slipped up, etc etc.

0

上一篇:

下一篇:

精彩评论

暂无评论...
验证码 换一张
取 消

最新问答

问答排行榜