Change name of imported type (aliasing)
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.
None.
Only metric to be measured here will be developers satisfaction rate on using Java after introducing this feature.
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.
import org.example.view.model.Employee as EmployeeView
import org.example.view.model.{Employee => EmployeeView};
import org.example.view.model.Employee as EmployeeView
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.
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
There are multiple workarounds on this problem, but all of them have their drawbacks:
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.
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.
Standard unit tests should be enough to properly test this feature.
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.
None.
Something similar would be partial path imports, as they could also elevate some of the similar pain points, and could be even more explicit when read:
The same already works for inner classes, so I don't see a reason why it wouldn't work here.