Skip to content

Instantly share code, notes, and snippets.

@cardil cardil/JEP.md

Last active Jul 9, 2020
Embed
What would you like to do?
[Draft] JEP - Change name of imported type (aliasing)

Summary

Change name of imported type (aliasing)

Goals

The goal is to make code more productive and clean in cases where multiple classes with same name must be used in code. It should relief a developers frustration in that situations.

Non-Goals

None.

Success Metrics

Only metric to be measured here will be developers satisfaction rate on using Java after introducing this feature.

Motivation

Situation that same class exists in code base is common. In most enterprise application there are multiple object models and there is also the code that maps values from one model to the other. Names of those models shouldn't be forged by developers, but business domain names that are used should be utilized. It's directly advised to do that be Domain-driven design (DDD).

Without such a feature developers are pushed to consider renaming a model classes to make them unique, to evade using fully qualified class names.

This feature is present in multiple languages. Most notable in Python, but also strongly present in JVM languages. Scala, Groovy and Kotlin all have this feature implemented. C# is also equipped with this feature.

Groovy

import org.example.view.model.Employee as EmployeeView

Scala

import org.example.view.model.{Employee => EmployeeView};

Kotlin

import org.example.view.model.Employee as EmployeeView

C Sharp

using EmployeeView = org.example.view.model.Employee;

Implementing this feature is asked by multiple developers and it will make Java on par with it's competitors and relief a developers frustration.

There are multiple threads with discussion on this topic. Naming a few:

It's also a topic on various conferences, must notably by Kevlin Henney.

I'm aware that this feature was proposed multiple times in the past (about 20 years ago , JDK-4194542, JDK-4214789) and it was rejected:

This is not an unreasonable request, though hardly essential. The occasional use of fully qualified names is not an undue burden (unless the library really reuses the same simple names right and left, which is bad style).

In any event, it doesn't pass the bar of price/performance for a language change.

I find this reasoning incorrect. As already mentioned, it is desired to have meaningful domain names, without need to suffix them with *Dto, *Entity, or *Data etc. A little bit different models of the same object are also desirable and directly advised by Clean (Hexagonal) architecture:

Typically the data that crosses the boundaries is simple data structures. You can use basic structs or simple Data Transfer objects if you like. Or the data can simply be arguments in function calls. Or you can pack it into a hashmap, or construct it into an object. The important thing is that isolated, simple, data structures are passed across the boundaries. We don’t want to cheat and pass Entities or Database rows. We don’t want the data structures to have any kind of dependency that violates The Dependency Rule.

Additionally as mentioned, situation is different then was in 1999 and Java's competitors, both JVM based and not, has this feature implemented.

Description

This feature should be implemented solely in Java compiler. Compiled code shouldn't be aware that aliasing was used.

package org.example.view;

import org.example.domain.model.Employee;
import org.example.view.model.Employee as EmployeeView;

interface EmployeeMapper {
  EmployeeView map(Employee employee);
}

To implement this changes to compiler should be made in the way that when compiler reads a java class file with lexer tokens should be renamed on the fly. In that way impact of this change will be minimized as further processed will not have access to this alias information as it will be gone at that point.

Some changes are probably required also to javadoc.

TODO: Further detailed description should be written

Alternatives

There are multiple workarounds on this problem, but all of them have their drawbacks:

Giving a unique name using prefix

With this alternative developer should give a unique simple name to all classed that might be in contact with each other, utilizing prefixes or suffixes.

class EmployeeView {
}
class EmployeeModel {
}

This approach is undesirable as names are forced to be concatenated with additional noisy additions. It directly violate naming principle of DDD and defeats usage on packages. If we need unique names, why we need a packages?!

It's also impossible if we don't control both classes. That might be the case when using some kind of RPC mechanism like SOAP, REST, or RMI.

Extend a class

With this approach developers might extend one of the classes, essentially making a wrapper that delegates operations to base class.

package org.example.view;

import org.example.view.model.Employee;

class EmployeeView extends Employee {
  private final Employee delegate;

  @Override
  String fullName() {
    return delegate.fullName();
  }
}

It also requires additional mapping from org.example.view.model.Employee object to EmployeeView wrapper, and extreme amount of error prone boilerplate code in wrapper class. It's also impossible to use when base class uses a final word, as it should . It's also might be impossible to use when using some kind of RPC mechanism.

Testing

Standard unit tests should be enough to properly test this feature.

Risks and Assumptions

There are usual risks of introducing new syntax to the language as exiting tooling must adjust to be able to work well. The risk is mitigated by choosing to limit this change to be solely compile time syntactic sugar.

Dependencies

None.

@MukundhanSampath

This comment has been minimized.

Copy link

MukundhanSampath commented Sep 10, 2019

+1

@greening

This comment has been minimized.

Copy link

greening commented Sep 15, 2019

+1

@olavoshibata

This comment has been minimized.

Copy link

olavoshibata commented Sep 24, 2019

+1

@idontusenumbers

This comment has been minimized.

Copy link

idontusenumbers commented Oct 1, 2019

-1; this leads to confusing code; It's not obvious the alias is not the actual class name. I've fallen victim to confusing aliases numerous times in other languages.

Should the alternatives section include using fully qualified names?

@rtc11

This comment has been minimized.

Copy link

rtc11 commented Oct 22, 2019

+1
Would have been awesome to do something like this aswell:

import org.example.Person as org.Person
import com.example.Person as com.Person

class PersonConverter implements Converter<org.Person, com.Person> {
    ...
}
@dornwelt

This comment has been minimized.

Copy link

dornwelt commented Nov 19, 2019

+1

@maxolasersquad

This comment has been minimized.

Copy link

maxolasersquad commented Dec 12, 2019

+1

@maxolasersquad

This comment has been minimized.

Copy link

maxolasersquad commented Dec 12, 2019

-1; this leads to confusing code; It's not obvious the alias is not the actual class name. I've fallen victim to confusing aliases numerous times in other languages.

Should the alternatives section include using fully qualified names?

IMHO, it only leads to confusing code if the person writing the code uses it in a confusing manner, which is true of ALL code features. This can lead to clearer code in many circumstances.

@negora

This comment has been minimized.

Copy link

negora commented Feb 3, 2020

+1

But, in my opinion, this feature SHOULD SUPPORT the possibility of using dots in the alias, in order to represent part of the path of the package which the class belongs to. That way, you can do this:

import org.example.entity.book.Book as entity.Book;
import org.example.ejb.book.model.Book as model.Book;
import org.example.ejb.book.model.brief.Book as model.brief.Book;

Instead of just adding an alphabetic prefix or a suffix:

import org.example.entity.book.Book as BookEntity;
import org.example.ejb.book.model.Book as ModelBook;
import org.example.ejb.book.model.brief.Book as BriefModelBook;

By using the former, you can work with part of the fully qualified name (FQN) of the class.

A stricter approach is supporting aliases only to import whole packages:

import org.example.entity.book as entity.book;
import org.example.ejb.book as ejb.book;
import org.example.ejb.book.brief as ejb.book.brief;

This way, the class short name remains intact. You could even force the alias to match the right-most elements of the package path. But that might be going too far. Specially if the package name is not descriptive and is not under your control.

@EthanWall

This comment has been minimized.

Copy link

EthanWall commented Feb 17, 2020

+1

@lucamgal

This comment has been minimized.

Copy link

lucamgal commented Mar 12, 2020

+1

@Touniouk

This comment has been minimized.

Copy link

Touniouk commented Apr 15, 2020

+1

@idontusenumbers

This comment has been minimized.

Copy link

idontusenumbers commented Apr 16, 2020

-1; this leads to confusing code; It's not obvious the alias is not the actual class name. I've fallen victim to confusing aliases numerous times in other languages.
Should the alternatives section include using fully qualified names?

IMHO, it only leads to confusing code if the person writing the code uses it in a confusing manner, which is true of ALL code features. This can lead to clearer code in many circumstances.

This feature is a trap, especially for beginners that haven't yet burned into their brain how it works because they haven't yet spent many hours trying to figure why some classes have names that differ from expectations. It's a tradeoff that let's individuals work in a more terse manor but results in less maintainable code and less team-frendly code. The feature invites using itself in a confusing manor; it's fundamentally a confusing feature. Can people figure it out? yes. In the end, does it help? I argue it will not.

This feature is only even relevant in 1 out of every ~100 files. Developers won't even realize this feature exists until they spend hours figuring out why something isn't what they expected. Many IDEs hide the imports section so the notation will be invisible!

More likely, this feature will be abused by programmers that don't like the name of a class. They will change the name in one file that they are working on. Another team member will work in their file unencumbered by by the name collision. A third programmer will work on a third file with a different alias. In all likelyhood, none of them will be able to use text search to find instances of the classes they expect to find in each others work. The doubly disparate names will make maintenance of non-authored files very difficult, especially at first. It will make a traditionally very consistent part of programming (which is already a very consistent, if not frustratingly so, endeavor) now inconsistent (but only in inconsistently and exceedingly rare circumstances).

Two developers working on the same exact kind of class in the same project under the same circumstances with the same skill will filp-flop the aliases each point to. One will chose a.MyClass > MyClassModel and one will chose b.MyClass > MyClassModel. That will be just one instance in what promises to be countless instances in a large repository.

A solitary developer working on their own repo will forget they aliased a class years later and spend hours tracking down what looks like an unclean build. They'll likely get to the point where they have to delete the entire local repo and re-pull, just to find it's still not working as expected.

It will make using IDES an absolute necessity so that find usages and goto definition work expectedly. You won't be able to reliably search your repo by copying and pasting a usage of a class. You won't be able to reliably search replace a class name let alone just search.

Reporting on tests, usages, dependency matrixes, Javadoc, etc will all now be hugely more complex or massively misleading. It will appear as though caches are corrupt and nothing is behaving properly.

It will be an unmitigated disaster to maintainability, readability, and tooling.

@TrustOkoroego

This comment has been minimized.

Copy link

TrustOkoroego commented Apr 18, 2020

+1

-1; this leads to confusing code; It's not obvious the alias is not the actual class name. I've fallen victim to confusing aliases numerous times in other languages.
Should the alternatives section include using fully qualified names?

IMHO, it only leads to confusing code if the person writing the code uses it in a confusing manner, which is true of ALL code features. This can lead to clearer code in many circumstances.

This feature is a trap, especially for beginners that haven't yet burned into their brain how it works because they haven't yet spent many hours trying to figure why some classes have names that differ from expectations. It's a tradeoff that let's individuals work in a more terse manor but results in less maintainable code and less team-frendly code. The feature invites using itself in a confusing manor; it's fundamentally a confusing feature. Can people figure it out? yes. In the end, does it help? I argue it will not.

This feature is only even relevant in 1 out of every ~100 files. Developers won't even realize this feature exists until they spend hours figuring out why something isn't what they expected. Many IDEs hide the imports section so the notation will be invisible!

More likely, this feature will be abused by programmers that don't like the name of a class. They will change the name in one file that they are working on. Another team member will work in their file unencumbered by by the name collision. A third programmer will work on a third file with a different alias. In all likelyhood, none of them will be able to use text search to find instances of the classes they expect to find in each others work. The doubly disparate names will make maintenance of non-authored files very difficult, especially at first. It will make a traditionally very consistent part of programming (which is already a very consistent, if not frustratingly so, endeavor) now inconsistent (but only in inconsistently and exceedingly rare circumstances).

Two developers working on the same exact kind of class in the same project under the same circumstances with the same skill will filp-flop the aliases each point to. One will chose a.MyClass > MyClassModel and one will chose b.MyClass > MyClassModel. That will be just one instance in what promises to be countless instances in a large repository.

A solitary developer working on their own repo will forget they aliased a class years later and spend hours tracking down what looks like an unclean build. They'll likely get to the point where they have to delete the entire local repo and re-pull, just to find it's still not working as expected.

It will make using IDES an absolute necessity so that find usages and goto definition work expectedly. You won't be able to reliably search your repo by copying and pasting a usage of a class. You won't be able to reliably search replace a class name let alone just search.

Reporting on tests, usages, dependency matrixes, Javadoc, etc will all now be hugely more complex or massively misleading. It will appear as though caches are corrupt and nothing is behaving properly.

It will be an unmitigated disaster to maintainability, readability, and tooling.

I totally agree with the dangers highlighted above. While enforcing restriction is good to ensure programmers write quality code, I still believe we should be given the freedom to take responsibility for our actions, are we not "18+" 😎. Too much control is not totally good, a bad programmer will still write an unmaintainable confusing code irrespective of the restrictions you impose.

Going by the argument above, Python would not have even been usable because it will be like a time bomb. But as the saying goes, python programmers "are consenting adults", and they still write quality software with it. Three JVM languages(Groovy, Kotlin, Scala) that have received good adoption, all have this feature. Why is this very difficult for Java? It's more than 20 years now, a request to make our life as java developers easier is not too much to ask.

@Hinara

This comment has been minimized.

Copy link

Hinara commented Apr 27, 2020

-1; this leads to confusing code; It's not obvious the alias is not the actual class name. I've fallen victim to confusing aliases numerous times in other languages.
Should the alternatives section include using fully qualified names?

IMHO, it only leads to confusing code if the person writing the code uses it in a confusing manner, which is true of ALL code features. This can lead to clearer code in many circumstances.

This feature is a trap, especially for beginners that haven't yet burned into their brain how it works because they haven't yet spent many hours trying to figure why some classes have names that differ from expectations. It's a tradeoff that let's individuals work in a more terse manor but results in less maintainable code and less team-frendly code. The feature invites using itself in a confusing manor; it's fundamentally a confusing feature. Can people figure it out? yes. In the end, does it help? I argue it will not.

This feature is only even relevant in 1 out of every ~100 files. Developers won't even realize this feature exists until they spend hours figuring out why something isn't what they expected. Many IDEs hide the imports section so the notation will be invisible!

More likely, this feature will be abused by programmers that don't like the name of a class. They will change the name in one file that they are working on. Another team member will work in their file unencumbered by by the name collision. A third programmer will work on a third file with a different alias. In all likelyhood, none of them will be able to use text search to find instances of the classes they expect to find in each others work. The doubly disparate names will make maintenance of non-authored files very difficult, especially at first. It will make a traditionally very consistent part of programming (which is already a very consistent, if not frustratingly so, endeavor) now inconsistent (but only in inconsistently and exceedingly rare circumstances).

Two developers working on the same exact kind of class in the same project under the same circumstances with the same skill will filp-flop the aliases each point to. One will chose a.MyClass > MyClassModel and one will chose b.MyClass > MyClassModel. That will be just one instance in what promises to be countless instances in a large repository.

A solitary developer working on their own repo will forget they aliased a class years later and spend hours tracking down what looks like an unclean build. They'll likely get to the point where they have to delete the entire local repo and re-pull, just to find it's still not working as expected.

It will make using IDES an absolute necessity so that find usages and goto definition work expectedly. You won't be able to reliably search your repo by copying and pasting a usage of a class. You won't be able to reliably search replace a class name let alone just search.

Reporting on tests, usages, dependency matrixes, Javadoc, etc will all now be hugely more complex or massively misleading. It will appear as though caches are corrupt and nothing is behaving properly.

It will be an unmitigated disaster to maintainability, readability, and tooling.

I disagree with you vision.

This feature is a trap, especially for beginners

It could be if it was an implicit conversion but we talk about a conversion written on the top of your code.

Many IDEs hide the imports section so the notation will be invisible!

That's a good point, and I understand why they did that but I also think that this is a bad practice as you have exactly the some problem that you denunciation just because of this feature. As how am I able to tell from which package does a class come from ? Is it the correct class, not one from another package ? So, the response to that for me is, configure correctly your IDE to prevent it to do this kind of behavior hiding you things, making them implicit.

More likely, this feature will be abused by programmers that don't like the name of a class.

So maybe would it be a good idea to warn when people trying to do that, only allow to use it without warning when you use it to prevent name collision.

One will chose a.MyClass > MyClassModel and one will chose b.MyClass > MyClassModel.

In anycase even if they did that, how would they flip-flop ? The name are colliding in this case preventing this case from happening.

A solitary developer working on their own repo will forget they aliased a class years later and spend hours tracking down

? I don't understand how, if your work on your code few years later, you should read it back. So if we skip the fact that import might be hidden in your IDE (as I think we could agree that it is not the best practice), you would definitively see the as in your import.

It will make using IDES an absolute necessity

How ? If you are not sure just search in your class where the other class is imported.

Reporting on tests, usages, dependency matrixes, Javadoc, etc will all now be hugely more complex.

Just replace the alias by the full name in this tool and it will work again, but if you think it is "hugely more complex" your choice.

@semanticbodger

This comment has been minimized.

Copy link

semanticbodger commented Apr 29, 2020

+1

This feature is a trap, especially for beginners that haven't yet burned into their brain how it works because they haven't yet spent many hours trying to figure why some classes have names that differ from expectations.

A while loop is a trap for beginners who haven't yet burned into their brain how to ensure that they don't spawn an infinite loop. That's why we should never ever add while loops to the language, either. Oh, wait...

It's a tradeoff that let's individuals work in a more terse manor but results in less maintainable code and less team-frendly code.

No. This is less maintainable and team-friendly code:

com.foo.app.legacy.modules.employees.factory.UserFactory userFactory = new com.foo.app.legacy.modules.employees.factory.UserFactory();
com.foo.app.search.libraries.consultants.factory.UserFactory consultantFactory = new com.foo.app.search.libraries.modules.consultants.factory.UserFactory();
com.foo.app.mobile.common.retirees.factory.UserFactory retireeFactory = new com.foo.app.mobile.common.retirees.factory.UserFactory();

And before you start thinking that this is not the "right" way to organize such classes, please step out of your bubble and realize that some people are working in huge, legacy, monorepos where there is no ability to go back - over millions of lines of code - and do it "the right way".

Of course, you don't have to do it this way. What usually happens is that the developers in these huge monorepos end up naming all of their classes like this: LegacyModuleEmployeeUserFactory(), SearchLibraryConsultantsUserFactory(), and MobileCommonRetireeUserFactory(). And that's a verbose, unreadable eyesore.

All of this gets solved if I can just alias these on import to ConsultantFactory, EmployeeFactory, and RetireeFactory.

The feature invites using itself in a confusing manor; it's fundamentally a confusing feature. Can people figure it out? yes. In the end, does it help? I argue it will not.

Creating a variable is the process of assigning a name to a value/data-structure. Import aliasing is the process of assigning a name to an imported resource. If someone finds that confusing, you should not allow them anywhere near your code.

This feature is only even relevant in 1 out of every ~100 files.

Just because you've seen this potential in only 1-in-100 files doesn't mean this is true for others. Also, this is a chicken-and-egg argument. The fact that Java has no aliasing of imports leads many devs to create ridiculously long names for their classes. So of course the current use case is slim, because we've been forced to created horrifically-long classes that contain most of the path in the naming convention.

Developers won't even realize this feature exists until they spend hours figuring out why something isn't what they expected. Many IDEs hide the imports section so the notation will be invisible!

Most IDEs hide the imports section by default because it's relatively rote and meaningless when you're troubleshooting the logic inside the class. If a developer can't figure out how to expand the import list at the top of the page, or change their IDE settings so that the import list isn't automatically collapsed, they need to be moved to the sales team, where their damage to the organization can be limited.

More likely, this feature will be abused by programmers that don't like the name of a class. They will change the name in one file that they are working on. Another team member will work in their file unencumbered by by the name collision.

This sounds like a control issue - like: "How dare you not use my class in the exact naming style that I chose to give it!!"

A third programmer will work on a third file with a different alias. In all likelyhood, none of them will be able to use text search to find instances of the classes they expect to find in each others work. The doubly disparate names will make maintenance of non-authored files very difficult, especially at first. It will make a traditionally very consistent part of programming (which is already a very consistent, if not frustratingly so, endeavor) now inconsistent (but only in inconsistently and exceedingly rare circumstances).

This is a great description for troubleshooting hurdles - in 1998, before we had IDEs where you could just click on the variable and see the source definition for its data type.

Two developers working on the same exact kind of class in the same project under the same circumstances with the same skill will filp-flop the aliases each point to. One will chose a.MyClass > MyClassModel and one will chose b.MyClass > MyClassModel. That will be just one instance in what promises to be countless instances in a large repository.

My gosh... the histrionics. We should also mention that, if this feature were implemented, cats and dogs may start sleeping together, global warming may accelerate by 50%, and Stack Overflow may be seized by Russian separatist terrorists.

A solitary developer working on their own repo will forget they aliased a class years later and spend hours tracking down what looks like an unclean build. They'll likely get to the point where they have to delete the entire local repo and re-pull, just to find it's still not working as expected.

Or... they could just click on the variable and be taken straight to the declaration...

It will make using IDES an absolute necessity so that find usages and goto definition work expectedly. You won't be able to reliably search your repo by copying and pasting a usage of a class. You won't be able to reliably search replace a class name let alone just search.

Absolutely necessary??? No. You can still read the code - if you can just be bothered to scroll to the top of the page. You spent a bunch of time wringing your hands over the IDE hiding the imports, but now you're worried that an IDE will be "necessary"?? Which is it? Are we using IDEs or not?? And who in their right mind is still coding in a plain ol' text editor??

So now we need to tailor the language constructs to make it easiest for those who are still coding in the 20th century???

Reporting on tests, usages, dependency matrixes, Javadoc, etc will all now be hugely more complex or massively misleading. It will appear as though caches are corrupt and nothing is behaving properly.

And COVID-20. Don't forget that it will absolutely spawn the next viral pandemic.

It will be an unmitigated disaster to maintainability, readability, and tooling.

UNMITIGATED DISASTER!!!!!!!

@idontusenumbers

This comment has been minimized.

Copy link

idontusenumbers commented Apr 29, 2020

A while loop is a trap

A while loop has much larger benefits and the infinite loop case is much easier to diagnose than criss-crossed aliases.

No. This is less maintainable

No, that's a contrived example of bad architecture.

huge, legacy, monorepos where there is no ability to go back

That's actually the easiest way to go back; automated refactoring works great, especially in monorepos.

All of this gets solved

It's not solved; what's being proposed here is a bandaid with significant unintended consequences, which I outlined.

Import aliasing is the process of assigning a name to an imported resource. If someone finds that confusing, you should not allow them anywhere near your code.

The proposal here is a name for a name for a resource. That's an additional layer of abstraction over the comparison you tried to draw. The problem with the confused developer isn't lack of experience, it's human nature.

because we've been forced to created horrifically-long classe [names]

If what you describe is true, this new feature will ENABLE clashing class names such that they will become more frequent and exacerbate the problem that the aliases create.

If a developer can't figure out how to expand the import list at the top of the page

It's not that they can't figure it out, it's that they won't think to.

they need to be moved to the sales team

That's rather mean spirited. There do exist junior developers; all senior developers were junior at some point.

This sounds like a control issue

And wanting to rename a class isn't a control issue?

This is a great description for troubleshooting hurdles - in 1998, before we had IDEs

You're repeating one of the points I made which is this feature basically necessitates the use of IDEs; which doesn't impact me but it sure impacts readability and understandability of code. Do you ctrl-click every single class name to make sure it's not from a package you didn't suspect? ... I don't either. This new feature will make that a more frequent worry (if you're lucky enough to even realize it might be happening)

My gosh... the histrionics.

It's not a fantasy, it's a reality that I have experienced in C#.

Or... they could just click

Which is 1 more step than the 0 which is necessary before this feature. The magnitude isn't like going from 5 clicks to 6 (also plus one), it's now, to understand your code, you need to start interacting with it.

Absolutely necessary??? No. You can still read the code

You just said argued three times that you can just use an IDE to work around the problems this causes. Which is it?

So now we need to tailor the language constructs to make it easiest for those who are still coding in the 20th century???

Maybe I wasn't clear. It will be nearly impossible without, but still difficult with an IDE.

@idontusenumbers

This comment has been minimized.

Copy link

idontusenumbers commented Apr 29, 2020

configure correctly your IDE to prevent it to do this kind of behavior hiding you things, making them implicit.

Hiding the import section is a productivity boost as it is exceedingly rare that I need to worry about the contents of the import section. With this change, that boost will be reduced if not eliminated.

So maybe would it be a good idea to warn when people trying to do that, only allow to use it without warning when you use it to prevent name collision.

That seems like a reasonable precaution.

One will chose a.MyClass > MyClassModel and one will chose b.MyClass > MyClassModel.

In anycase even if they did that, how would they flip-flop ? The name are colliding in this case preventing this case from happening.

The example I give shows that two developers aliased two classes to the same name in two different files; sorry if that wasn't clear.

? I don't understand how, if your work on your code few years later, you should read it back.

You would need to read more carefully than if this feature were not adopted.

So if we skip the fact that import might be hidden in your IDE (as I think we could agree that it is not the best practice)

I'm not sure where you get best practice; I believe hiding may be a default behavior. It's been so long that I've had that turned on that I can't even remember.

How ? If you are not sure just search in your class where the other class is imported.

"Just search" can be a highly disorienting task, especially when the alternative is just continuing to read. The big issue here is that you aren't just omitting the package, it's that the class name can be unique to this one file and also clash with commonly uses classes from other files.

Consider List. Right now, if I see that I know its java.util.List or java.awt.List. This proposal lets someone rename ArrayList to List, which is exactly what it is NOT. Reading the code, I might see that some method takes a List, which I presume to be a List interface but is in fact a locked down implementation. I then find myself trying to figure out what the heck is going on.

@BakoviDagi

This comment has been minimized.

Copy link

BakoviDagi commented Apr 29, 2020

Consider List. Right now, if I see that I know its java.util.List or java.awt.List. This proposal lets someone rename ArrayList to List, which is exactly what it is NOT. Reading the code, I might see that some method takes a List, which I presume to be a List interface but is in fact a locked down implementation. I then find myself trying to figure out what the heck is going on.

That's a fair point. Perhaps the compromise would be not allowing the class name to change, and just using a part of the package to alias, something like import java.awt.List as awt.List. That way some of the more complicated cases would be consultant.UserFactory() and employee.UserFactory()

I'm of the opinion that if people want it, it should be provided as an option, that way coders have a choice. At my work, we've started failing builds when classes don't have the appropriate javadoc. If you're so opposed to it, I'm certain somebody that hates it enough will make a maven/gradle plugin that fails the compilation when aliasing is used, but there are people that would like this feature so they should be allowed to have it

@idontusenumbers

This comment has been minimized.

Copy link

idontusenumbers commented Apr 29, 2020

There have been a lot of features that give developers options but have been intentionally omitted due to other consequences like readability, understandability, or complexity. I believe the trade offs outway the adoption of this proposal.

@Hinara

This comment has been minimized.

Copy link

Hinara commented Apr 30, 2020

? I don't understand how, if your work on your code few years later, you should read it back.

You would need to read more carefully than if this feature were not adopted.

Not really more, you should also read back your import as you don't know for sure to which class they refer.

configure correctly your IDE to prevent it to do this kind of behavior hiding you things, making them implicit.

Hiding the import section is a productivity boost as it is exceedingly rare that I need to worry about the contents of the import section. With this change, that boost will be reduced if not eliminated.

I'm not sure if it is really the good way to boost productivity, I understand that scrolling each time under all import might be beneficial, but what if instead of hiding the import, the IDE would open files directly after the import section ?

One will chose a.MyClass > MyClassModel and one will chose b.MyClass > MyClassModel.

In anycase even if they did that, how would they flip-flop ? The name are colliding in this case preventing this case from happening.

The example I give shows that two developers aliased two classes to the same name in two different files; sorry if that wasn't clear.

Okay, I think I get it, effectively a.MyClass and b.myClass are colliding, but defining an alias for each of them called MyClassModel in a different class, make that they collide again pushing you to you aliasing again, Which is interesting. What about a rule to warn if you are aboye a certain aliasing level ?

So if we skip the fact that import might be hidden in your IDE (as I think we could agree that it is not the best practice)

I'm not sure where you get best practice; I believe hiding may be a default behavior. It's been so long that I've had that turned on that I can't even remember.

So yes I understand that it was for "productivity", but I mentioned also in this comment how to maybe think about another solution to boost productivity without hiding a part of the code. For me hiding the import part is really not a good way to handle this, as it makes implicit all classes that you are using if you are not giving there full package name before using them. And sometimes you don't choose to have two classes with the same name, sometimes, libraries provides you some classes with the same name.
One of the thing you said on the previous one was about being forced to use IDE, but it's a bit paradoxal, because

  • IDEs are the one to hide this part, but allow you to see the original location of a class by passing your cursor on them.
  • Text editors will most likely not do that (except if they have plugin but if it is the case it's most likely that your text editor is an IDE), so you will have to read your import section to be sure about the class which correspond to a given name.

Which gets me to the next point

How ? If you are not sure just search in your class where the other class is imported.

"Just search" can be a highly disorienting task, especially when the alternative is just continuing to read. The big issue here is that you aren't just omitting the package, it's that the class name can be unique to this one file and also clash with commonly uses classes from other files.

First of all why omitting the package should be fine ? The response is productivity, but if you accept that response, why would you prevent a user to omit the package name by using aliases ? I agree that renaming a class is not the best practice as it can loose meanings, but that's the developper job to decide about it, elsewhere would you prevent any developper from choosing a variable name ? BakoviDagi can work, but can collide with some other package name, so I think it a way but I can't tell if it's a good one or bad one. On small project size with not a lot of dependencies, where you can manage to handle all of them, ok. But on a big project, I'm not sure.
On the other point about continuing to read that's why lots of people are using IDE. Because they enable you to have more context when you are working only on a part of the code, but that's also the problem as you let a big part of understanding to your IDE, without knowing everything in your code, and hope that it will work, relying on your IDE.

@bytebodger

This comment has been minimized.

Copy link

bytebodger commented Apr 30, 2020

I agree that renaming a class is not the best practice as it can loose meanings, but that's the developer job to decide about it, elsewhere would you prevent any developer from choosing a variable name ?

Bingo! You can rename variables all day long. Having aliased imports - or not having them - doesn't change this fact. The idea that someone would oppose aliasing because they're afraid that their class will be "renamed" is just... silly. Without aliasing, I can always do this:

import com.fruits.core.base.fruits.TheBigHairyRidiculouslyNamedBanana 

TheBigHairyRidiculouslyNamedBanana pumpkin = new TheBigHairyRidiculouslyNamedBanana ();

Obviously, the code above could cause some confusion - even without aliasing. TheBigHairyRidiculouslyNamedBanana is most certainly not a pumpkin. But you know how you "solve" this problem? Education. Best practices. Code reviews. If that's not sufficient, then you need to get the guy who's instantiating this class as pumpkin off the team. (And no, I don't care if that sounds harsh.) And if the education / best-practice / code-review processes are just too much for you to bear, then you might want to consider a career in sales. (And no, I don't care if that sounds harsh, either.)

I've seen this proposal shot down for twenty years - usually by one guy on the core team who looks at it and says, "Yeah... nope. You don't need to do that." But most language improvements aren't about what you need to do. They're about simplifying the things that you already have to do (manually) all over your codebase.

No one needs lambda expressions. Everything you can do with a lambda expression, you can also do without one. That doesn't make the lambda expression "bad" or "wrong". And if you really wanna get into it, you know what a lambda expression "does"? It's an abstraction for some other, more verbose process.

It's really cute that some people on this thread don't think that naming collisions should be an issue. I'm glad that they've never had to work in a monorepo with many dozens of packages and millions of lines of code. But for those of us who've had to work in some huge, heavy-duty kinda environments, this isn't a problem you can just "fix" with clever refactoring.

Last year I was working at a huge health insurance aggregator and we had One Big Hairy Monorepo that housed millions of lines of code. Take a guess at how many types of "User()" or "Api()" classes there were in that codebase, strewn across a great many packages? No one wants to reinvent the wheel by rewriting existing classes. And the authors of those original classes knew that they'd need to be repurposed throughout the app - across many different packages. The authors also knew that Java affords no import aliasing. So these are the kinda (ridiculous) class names that you ended up having to deal with:

import com.companyname.core.partners.aetna.apis.channelpartners.regional.southeast.someprovider.PartnerAetnaChannelPartnerRegionalSoutheastSomeProvider;

PartnerAetnaChannelPartnerRegionalSoutheastSomeProvider someProviderApi = new PartnerAetnaChannelPartnerRegionalSoutheastSomeProvider();

If you think I'm exaggerating, I assure you that I'm not. Personally, I don't care if you name your class TheQuickBrownFoxJumpedOverTheLazyDog. But it's silly to think that I can't just do this:

import com.companyname.core.partners.aetna.apis.channelpartners.regional.southeast.someprovider.TheQuickBrownFoxJumpedOverTheLazyDog as BrownFox;

BrownFox brownFox = new BrownFox();

And why can't we do that?? Because someone coding in Notepad might not be able to quickly surmise the class definition?? Because you're gonna be soooo offended that some other coder aliased your prized class name?? C'mon, mannn...

Despite the claims of UNMITIGATED DISASTER!!!, the simple fact is that import aliasing is available in many other languages. Go google all the people telling horrible tales of woe about the occasions where this evil import aliasing caused them endless headaches and ruined their codebase.

Go ahead. I'll wait...

Then google all the occasions where people coming over to Java from other languages are saying, "Hey, wait... How do I alias an import in Java???"

Despite the hyperbolic claims of woe, import aliasing provides two extremely useful functions:

  1. When you're creating a new class, you can name it as succinctly as possible, without any fear that future devs will have to deal with fully-qualified class names if they choose to import your package/class. If your package has one logical declaration for User(), then just name your class User(), and you can be content that if putative future devs have a naming collision with some other User() class, they can alias it on an as-needed basis.

  2. When you're dealing with some "outside" package that you've imported, and the original developer felt the need to name the class TheQuickBrownFoxJumpedOverTheLazyDog(), you can easily alias it down to a name that's more appropriate in your current code. And if the original dev called his class User(), and you already have 3 other definitions for User() in your current code file, you can easily alias them so that they make good sense to you - or anyone else who happens to be reading your code.

If I've imported 3 different User() classes from 3 different packages, the idea that I need to refer to them all by their fully-qualified name is just silly.

@woeltjen

This comment has been minimized.

Copy link

woeltjen commented May 20, 2020

+1

private static class Orange extends blah.blah.Apple {}

We already have the mean scary hypothetical footgun at our disposal.

import blah.blah.Apple as Orange;

We'd like the useful syntactic sugar, too.

@kintarowins

This comment has been minimized.

Copy link

kintarowins commented May 27, 2020

This feature is a trap

Java has already matured past the for-beginner's stage it is laughable to think this will confuse beginners.

@cyraid

This comment has been minimized.

Copy link

cyraid commented Jul 8, 2020

I'm reading the one guy who's against it, and pretty much everyone is for it.. And I think to myself.. Why do all the other languages do it? Oh yeah, because that one guy isn't the only one using it.. It's everyone using it. Why build a language for one person, and not everyone else who's using it? People just jump ship if a language is poor enough, and go to C# (for example).

@idontusenumbers

This comment has been minimized.

Copy link

idontusenumbers commented Jul 8, 2020

Java has already matured past the for-beginner's stage it is laughable to think this will confuse beginners.

So Java is simultaneously not for beginners and for beginners?

Why do all the other languages do it? Oh yeah, because that one guy isn't the only one using it.. It's everyone using it.

This is precisely the problem with this feature. With lots of people using a code base, the aliases will lead to more confusion, not less.

A language that does everything and with no foresight will die. Perl added lots of for-convenience language features; it made reading the code impossible and now the language is practically dead.

If I was being totally selfish about this, I wouldn't have commented. I won't use this feature in any of my code and I'll make sure the style guide for any project I'm on excludes its use. Its all the other folks that will suffer. Just trying to give everyone the heads up.

Aside from that, I don't see the appeal to majority as a valid argument.

@semanticbodger

This comment has been minimized.

Copy link

semanticbodger commented Jul 8, 2020

This is precisely the problem with this feature. With lots of people using a code base, the aliases will lead to more confusion, not less.

A language that does everything and with no foresight will die.

Yeah. Remember when people used to use C#? Too bad they added aliasing - and now it's dying.

@cyraid

This comment has been minimized.

Copy link

cyraid commented Jul 8, 2020

I guess that means python is dying too, and all the other languages that have implemented it. Java is so behind. I'm using it for a project because I have to but can't want to get back to C# because it's things like this which make me dislike java. It's such a verbose language.

C# also has extensions, which I wish java had.

@idontusenumbers

This comment has been minimized.

Copy link

idontusenumbers commented Jul 8, 2020

I feel like I laid out quite a few valid points which I'm open to discussing. I don't think the sarcasm or fallacious appeals are helping forward the conversation.

@cyraid

This comment has been minimized.

Copy link

cyraid commented Jul 8, 2020

Nah, I'm done with Java. Why don't you argue those points with the languages that already use it, and the people that are happy with it. Didn't cause them such strains.

@cardil

This comment has been minimized.

Copy link
Owner Author

cardil commented Jul 9, 2020

I would like to say that now I'm working on Golang. That language that's getting traction and lots of stuff being built with it like: Kubernetes, Docker, Terraform, etc.

Go was built with simplicity in mind. Only essential features has been implemented. Features like generics ware purposely declined There's only for loop, no exceptions. And because of that simplicity it's a real joy to work with. I assure you.

Go has aliasing too.

import anythingyoulike "github.com/some/lib/pkg/thing"
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
You can’t perform that action at this time.