Skip to main content

If you could get rid of one thing from Java...

24 replies [Last post]
johnm
Offline
Joined: 2003-06-06

Reply viewing options

Select your preferred way to display the comments and click "Save settings" to activate your changes.
kcpeppe
Offline
Joined: 2003-06-15

> > The fact is, the new
> > for syntax encourages people to violate
> encapsulation
> > and in doing so, violate DRY.
>
> Can you explain how the new for syntax (you mean the
> for-each loop, right?) encourages people to violate
> encapsulation and repeat themselves?
>
> Monika.

actually, using iterators incourages people to violate encapsulation (it's not a horrible violation). The new for loop just makes it a bit easier.

The "purist" way of doing this is to delegate. In this case, delegation requires that you pass in the code to be executed against every element in the collection (or every element that meets some selection criteria against specifed by a conditional passed to the collection). But, since we have no real mechanisum to achieve this in Java (one could contrive one but....), we pull objects from the collection.

More importantantly, is the violation of DRY. In this case, when we pull and object from a collection, we end up having to repeat the control logic for doing so (Iterator and Enumeration). Encapsulating that behavior into the collection would but it to bed once and for all. That said, this is not a horrible violation of dry (though it does lead to code bloat) because collections are an integral part of the JDK API and as such, we should expect that they are stable. If they were not stable, we would need to troll through out code finding all the places where we placed this control logic and then modify it to conform with the change. This is sometimes known as "shotgun surgery". We can't really deprecate Enumeration in favor or Iterator with causing people some real problems can we ;)

patrikbeno
Offline
Joined: 2004-10-11

Ok, I'll try it.
[b]What you cannot [u]effectivelly[/u] do without generics?[/b]

It's a little longer but if you want answers, you'll find some.

Summary in a few words: [b]better & more flexible frameworks[/b]

Suppose you have this generic class (and forgive me if this example is a little weird)
[code]
/* implementations ommitted */
abstract class Bank
{
void registerCustomer(TCustomer c);
TCustomer findCustomer(...);
TAccount findAccount(...);
...
... and plenty other methods (say 20)
}

- and same for every type variable (Customer, Account, ...)
[/code]

I know it seems little verbose but it's only declaration.
The point that makes it great is elsewhere. Read on.

You have some generic implementation, with several abstract methods that need to be implemented by subclass.
Type variables (TCustomer, TAccount, TProduct, TTransaction) are used intensivelly in whole implementation and especially, they are supposed to be used extensivelly in the implementations of the abstract methods.

You define your own implementation for every of the type variables (Customer, Account, Product, Transaction). You are customizing your framework (some generic bank implementation) for your particular customer (bank). It is very common that you will need to extend those base classes because your new customer requires some additional or modified functionality.

Without generics, you have one choice:
- create subclass for every customized type
- since you cannot change inherited method signatures, you need to cast every object returned by inherited method to your customized types before you use them.
- you are exposed to the risk that one of your colleagues creates instance of unsupported type (because [i]"API requires Customer so let's create some Customer, errr, who was supposed to know that special CustomizedCustomer is required elsewhere in the application, my use case worked for me...[/i]")
- let's say you have total base (inherited) functionality about 100K lines in your base abstract classes, and another 100K lines is provided by you in your subclasses.
- now considering overall size and complexity of the application, you have to use old API that does not match application model, you have to do way tooooo much redundant type casting, etc

You might object that you will use composition pattern.
However, you cannot do this because you composition objects are not compatible with your framework (base abstract type Bank, Customer, Product, Account, Transaction ...)
And even if you could do this, Creating 10-100 delegate classes just to make application type safe is overhead

With generics, you will do just this:
[code]
class MyCustomer extends Customer {
void extraMethod(){}
}
class MyAccount extends Account {...}
class MyProduct ...
class MyTransaction ...

and finally
class Mybank extends Bank
{}
[/code]
... and implement those abstract methods or override inherited...

And you have:
- fully customized domain model
- every method accepts customized types only
- every method [b]returns[/b] customized types (do this without generics!!!)
- no need to cast everything
- .... many more but who does not want to hear that ...

pbk_at_sun_com
Offline
Joined: 2004-11-12

In the HotSpot Java virtual machine implementations, there is no additional overhead for making every object lockable.

Each object has a header with space for two pointers. One pointer is a refernce to the class of the object and the other is used for various other things, including pointing to lock information if the object is locked. But even if we used some other scheme for locking objects we'd want that space for the other uses: e.g., as a forwarding pointer during garbage collection, for holding the hash of an object if it has one, random flag bits that the VM needs, etc.

It's an engineering tradeoff between using more space close to the object that can be accessed quickly versus taking more time to get to that information if we put it further from the object. We think that a 2-word header is the right tradeoff.

coxcu
Offline
Joined: 2003-06-11

"4 bytes less per object"?!?

Is this true for all objects on all common JVMs?
If so, surely some optimization could be done to lower it. After all, many, if not the overwhelming majority of classes have no synchronization at all.

dgriffit
Offline
Joined: 2004-10-13

Last I heard, most commodity JVM's do include a monitor pointer on each object. There has been some research work on optimizing this, but it's not as easy as it would seem.
If I'm wrong on this, I'd love to be corrected.

murphee
Offline
Joined: 2003-06-10

Sun has done this in recent Monty (Hotspot for J2ME JVMs).
In Monty, objects only have 4 byte headers (which is the Type Identification Block, basically a pointer to the class information). The Monitor information is not stored with each object, but it is only created when needed (as far as I see it; I only got this from some online slides from JavaOne).

kcpeppe
Offline
Joined: 2003-06-15

> oh no no no :-)
>
> you do not want generics because you think it is a
> bad idea, you don't need them

Not only do I not need them... I don't really need typing but that said, I'm willing to live with it ;)

(or you think you
> don't). You do not even care about how the are
> implemented. In your case, it's just 'hate at first
> sight' :-)

Sorry, I don't really function that way. I look at a technology and try to make a determination on a cost benefit basis. For example, you won't see me putting the for syntax on the list even though I believe that the polymorphic way with closures is a far superior way of achiving the same effect. The fact is, the new for syntax encourages people to violate encapsulation and in doing so, violate DRY. But since people do this anyway (and heaven forbid we alter the language to prevent this fomr happening ;)) it's syntax is only mildly offensive.

In the case of generics, I have not seen where they help all that much. I certianly can see where they've hindered (in cost of syntax and inconsistancies that they've introduced). Hence cost - benefit = loss IMHO. Until someone comes up to me and says... look this is something that you couldn't have done with generics.. the equation stays the same. Until someone comes up and says... look at the savings because of generics... same result... generics = loss. So far in several days of talking, all you've been able to do is spout the same old stuff that IMHO hasn't done anything to impress me for the last year.

The question here is, if there was one thing I could get rid of.... and since generics adds relativily little for the cost it imposes... generics gets the nod. As Trump would say... generics.. your fired ;)

>
> There are many people who think they need generics,
> that they are best solution for [i]some[/i] of their
> problems. These people have sound reasons why they
> ask for generics.

I respectfully have not seen anyone put forth an arguement that was strong enough to warrent changing the language.

>
> If you do not belong to them, it does not mean
> generics are bad thing. You think you can live
> without them. Then live without them, don't use them.
> But don't force us to throw them away because of you.

I would argue that the onus of proof to change the language is on those that think they need generics. We should not have to define what is there. Unfortunately this premise that was in place has broken down and hence we are stuck with this hidous implementation.

Everything I've read and experienced say that less syntax helps make us productive. I don't feel the need to appologize for saying.. hey more syntax... not good! lets think about this!

monika_krug
Offline
Joined: 2004-10-14

> The fact is, the new
> for syntax encourages people to violate encapsulation
> and in doing so, violate DRY.

Can you explain how the new for syntax (you mean the for-each loop, right?) encourages people to violate encapsulation and repeat themselves?

Monika.

vhi
Offline
Joined: 2004-10-11

In Ruby, the iterations are much more graceful due to internal Iterators.

E.g.

list.find {|item| if item=="something"}

Here, 'list' has a 'find' method which internally iterates through its elements, and then executes the block within the braces on each element and returns if the block evaluates to true.

Another example of a for-each loop is:

list.each {|item| print item}

As you see, it is bit more graceful.

Though something like this can be done in Java (using interface, anonymous classes, and implementing internal iterators), it is not the _official_ way. This is because doing it in Java under present conditions is much more verbose and unreadable than external Iterators.

Now, currently Java breaks encapsulation (well somewhat) because it exposes Iterators (though you can say Iterators are really an abstraction over the list's interals and thus do not really break encapsulation). This is because, in pure OO, you send messages to objects, and objects perform some operation for you (like 'find'). It is generally not considered good OO by purists when an object returns another object (i.e. Iterators) using which you have to perform an operation (i.e., iterate using the Iterator _on your own_). In case of Ruby (a pure OO language), it provides you with iteration operation also; you just have to pass it the code you want to execute.

saintjohn
Offline
Joined: 2004-10-25

Agree.

jwenting
Offline
Joined: 2003-12-02

> All deprecated classes/methods between JDK 1.0
> through ... X where you guys decide what X should
> be.
>

Well said. It's high time for a big cleanup operation to remove all deprecated stuff.
Let's say that deprecated stuff be kept for 2 more releases.
So something deprecated in 1.4 is scrapped in 1.6, something deprecated in 1.5 is scrapped in 1.7, etc.

timbell
Offline
Joined: 2003-06-10

How about two things?

1) [b]java.lang.Object.finalize()[/b]

2) [b]java.lang.ThreadGroup[/b]

Both of these were experiments that did not end well.

For more on this topic, take a look at:
[b]"Effective Java Programming Language Guide"[/b] by Joshua Bloch:
http://java.sun.com/docs/books/effective/

dgriffit
Offline
Joined: 2004-10-13

Monitors as part of every object, rather than separate Lock objects. Keep the synchronized statement, but require that it take Lock objects as arguments. Lose the synchronized method flag. Much more clarity, much better control, and 4 bytes less per object. Sadly, it's way too late to make this change.

patrikbeno
Offline
Joined: 2004-10-11

I think this depends on what you need. For many use cases the built-in mechanism is the best and managing extra Lock instance is overhead (at least maintenance overhead). For all other scenarios that require more flexibility, we are now lucky to have java.util.concurrent package.

kcpeppe
Offline
Joined: 2003-06-15

generics

patrikbeno
Offline
Joined: 2004-10-11

;-) the one who agreed to disagree ;-)

kcpeppe
Offline
Joined: 2003-06-15

> ;-) the one who agreed to disagree ;-)

I said disagree, not be quiet about it :)
And, you keep continuing to say.. this is great.. but it's broken... It's like the two old guys in the resturant.... first one says... the food is horrible.. and the second say, yes, and the portions are small also!!!

patrikbeno
Offline
Joined: 2004-10-11

oh no no no :-)

you do not want generics because you think it is a bad idea, you don't need them (or you think you don't). You do not even care about how the are implemented. In your case, it's just 'hate at first sight' :-)

As for me, on the other hand, I think generics are good idea, and I have whole bunch of resons for this claim, I only insist the need to be implemented differently.

There are many people who think they need generics, that they are best solution for [i]some[/i] of their problems. These people have sound reasons why they ask for generics.

If you do not belong to them, it does not mean generics are bad thing. You think you can live without them. Then live without them, don't use them. But don't force us to throw them away because of you.

ricky_clarkson
Offline
Joined: 2004-06-28

Except that generics impose their ugly faces on people who don't use them.

Look at the Javadocs for java.awt.Collection ( http://java.sun.com/j2se/1.5.0/docs/api/java/util/Collection.html )

interface Collection

boolean add(E o)

patrikbeno
Offline
Joined: 2004-10-11

Well, is the only reason is JavaDoc, you are not fair.
You code can be completely free of generics so what is your problem?

afreije
Offline
Joined: 2004-10-14

java.util.Date should have been immutable

tsinger
Offline
Joined: 2003-06-10

Same for Point, Dimension and so on.

cowwoc
Offline
Joined: 2003-08-24

All deprecated classes/methods between JDK 1.0 through ... X where you guys decide what X should be.

Deprecated classes/methods that are left around for too long cause usability problems. There should be only one way to do any one thing in Java to avoid confusion. I'm not refering to "helper classes/methods". Those are fine. I'm talking about having a billion different image types and different ways to build images. The "new way" and the "old way". There should only be one way.

monika_krug
Offline
Joined: 2004-10-14

There should not only be one way to achieve something, particularly if there have previously been various ways.

But maybe some time the methods that were already deprecated in JDK 1.0 and 1.1 should be removed. This would make the JRE more efficient, wouldn't it?

Monika.