Should I avoid commonly used class names? - java

Some class names are so "generic" that they are often found in several different packages, including in libraries and application code. Some examples:
Comment
Component
Factory
Location
Region
In my IDE, attempting to auto-complete the import for a class like one of these summons several competing suggestions.
When naming classes, is it a good idea to avoid class names already used elsewhere?
For some of these examples, I would imagine that using such class name is discouraged because it is simply not meaningful enough (e.g. Factory), but I am wondering whether it is discouraged to use a class name because it is used (frequently) elsewhere.

You should use class names where they make the most sense for you. None of the names above that you've proposed are off limits, and there's no reason why you can't use them (assuming a language that supports namespaces and can avoid naming conflicts in this way).
However, you may consider drilling down to class names that are more specific and precise, which will better describe the meaning of the objects in your code. For example:
Instead of Comment: LineComment or BreakComment could easily be class names in a compiler project where you would like to create semantic blocks for comments.
Instead of Component: ListComponent, CalendarComponent, or ViewComponent make particular sense when implementing a UI library where you have class-based components.
Instead of Factory: PizzaFactory makes more sense if you're trying to make pizzas!
Instead of Location: GeographicLocation or SemanticLocation makes more sense when implementing a directions based navigation app, and you're trying to distinguish between '45 deg N, 77 deg W' and 'next to the pizza place'.
Region: CodeRegion could be used in a compiler, and GeographicRegion could be used in a Maps app.
If you're afraid to be specific, namespaces and packages help. However, there is nothing discouraging you from using the same name for a class as another package where it makes sense. The class names specifically aren't copyrighted, and most IDEs now are smart enough to make distinctions between what packages you're referring to when using autocompletion.
For the most part, specificity is helpful in assisting other developers to read your code, which every developer can appreciate!

Comment, Region, and Location seem fine. Personally, so subjectively, Component and Factory are definitely too common to use but objectively I can't think of any conventional reason not to use them as names. I'd definitely try and couple those names with their respective usage, for example; TaskFactory, WidgetComponent, ButtonFactory, etc.

Depends if we are talking about business or technical part.
In technical part: using common names is actually a way to let others know about the patterns used, Factory is a good example - when you see a class named like SomethingFactory, you can expect a Factory Pattern. It goes further to frameworks, libraries etc. - SomethingAutoConfiguration with Spring-Boot, SomethingEntity with JPA, I think with frontend frameworks (React, Angular) Component is a really common word. So ye, by all means, use them, as long as you use them correctly.
In business part: simple, if those words describe your business domain, then by all means use them. Don't try to invent some fancy names (or thesaurus!) just because the words seem common, it's your business domain - it's sacred.

Related

Why is it not recommended to store constants in a separate class?

It's been told me (and I have seen this statement in a few other places) that it's not recommended to store your constants in a separate class in Java, in order to use them in the other classes. But I haven't seen anywhere WHY is it so. What is the reason I should not store them in their own interface/class?
I came from C to Java and in C i would just make a .h file where i defined constants with #define
Constants in a dedicated file are frowned upon for stylistic reasons. Having a class dedicated to constants can encourage developers to add increasing numbers of unrelated (undocumented?) constants to a file that slowly bloats out of control.
By contrast, having constants associated with the classes they are related to is a more scalable and readable design.
So you can be an engineer and measure constants and their locations as a technical choice. This is great and fine when you work on performance critical systems or on cool small snippets. Once your application tends to grow however, it becomes harder and harder to grasp the business requirements and end-user needs reflected in the code.
So instead of thinking about style -- separate class, properties file or nested inside a class -- I tend to follow domain driven design -- if the set of constants exclusively belong to a specific class (entity), nest the constants; if the concept touches more than one of the entities in your domain model, feel free to make it a separate entity.
And please do remember, that since Java 5, you do have enums at your disposal.
A separate constants class is not object-oriented design. In OO, a class (or interface) represents a contract, and a class which only contains constants does not define any contract.
Another object-oriented consideration is that a separate constants class encourages misuse of inheritance. Inheritance is supposed to indicate that a class fully adheres to the contract defined by another class or interface. Inheritance should not be used just to share functionality or constants; that's what public methods and fields are for. Thus, this code is incorrect:
class SomeApplicationClass
implements ScrollPaneConstants // Incorrect, import ScrollPaneConstants instead
Issue is that they should be living outside of your source code entirely. You should be using something like Apache Commons Config, or at least loading from a .properties file.
I will also note that I'm interpreting "single" with respect to a reasonable scope. For instance, there should not be one Config file for all Java developers used stored on Google's servers with a request form for modifying. There probably should not be done for your entire code base; however, per UOR or package is a reasonable scope, and is the one I use in practice.

What is the suggested way to name Java packages?

I've seen lots of examples like com.mycompany.someapp. Seems to be the reverse of the domain. Which actually makes sense to me.
But at the end of the day, does it really matter? We are a small shop so maybe we don't see the benefits of proper domain naming.
So, is it good practice to name it to match the domain? If so, why?
Extracted from the link to Naming a Package (Java Tutorial) in Andrew's comment: (I claim no originality or ownership of the following).
Naming a Package
With programmers worldwide writing classes and interfaces using the Java programming language, it is likely that many programmers will use the same name for different types. In fact, the previous example does just that: It defines a Rectangle class when there is already a Rectangle class in the java.awt package. Still, the compiler allows both classes to have the same name if they are in different packages. The fully qualified name of each Rectangle class includes the package name. That is, the fully qualified name of the Rectangle class in the graphics package is graphics.Rectangle, and the fully qualified name of the Rectangle class in the java.awt package is java.awt.Rectangle.
This works well unless two independent programmers use the same name for their packages. What prevents this problem?
Naming Conventions
Package names are written in all lower case to avoid conflict with the names of classes or interfaces.
Companies use [their] reversed Internet domain name to begin their package names—for example, com.example.mypackage for a package named mypackage created by a programmer at example.com.
Name collisions that occur within a single company need to be handled by convention within that company, perhaps by including the region or the project name after the company name (for example, com.example.region.mypackage).
Packages in the Java language itself begin with java. or javax.
In some cases, the internet domain name may not be a valid package name. This can occur if the domain name contains a hyphen or other special character, if the package name begins with a digit or other character that is illegal to use as the beginning of a Java name, or if the package name contains a reserved Java keyword, such as "int". In this event, the suggested convention is to add an underscore. For example:
Legalizing Package Names Domain Name Package Name Prefix
hyphenated-name.example.org org.example.hyphenated_name
example.int int_.example
123name.example.com com.example._123name
Happy coding.
Matching the domain gives you greater confidence against name collisions. It's probably more important to designers of 3rd party libraries than you and your app.
Yes, that's the suggested convention in the Java Language Specification, section 7.7.
If unique package names are not used, then package name conflicts may arise far from the point of creation of either of the conflicting packages. This may create a situation that is difficult or impossible for the user or programmer to resolve. The class ClassLoader can be used to isolate packages with the same name from each other in those cases where the packages will have constrained interactions, but not in a way that is transparent to a naïve program.
You form a unique package name by first having (or belonging to an organization that has) an Internet domain name, such as sun.com. You then reverse this name, component by component, to obtain, in this example, com.sun, and use this as a prefix for your package names, using a convention developed within your organization to further administer package names.
You don't have to follow the convention, but it's generally considered good practice. After all, suppose at some point in the future you want to release some of your code as open source - but you want to avoid naming collisions. At that point, you really ought to follow the same conventions as everyone else - and as it doesn't hurt to do so from the start...
The idea behind using domain name is to avoid namespace collisions in packaging. This only works if everyone follows the convention. So, yes, the convention is important. That said, if you never plan on exporting your code as an API or providing it to a third party, it's likely there is little downside to using whatever package name you feel like.
Practically speaking I like it for a number of reasons:
It gives users an easy place to go to just from looking at the package name
It avoids collisions between packet names (i.e. two "media" packages could be very likely otherwise)
It helps identify the same author over separate pieces of software
It keeps package names roughly the same length (ok, this is just an aesthetic point but I like it!)
As well as this, it's also recommended in the JLS. It's not a requirement, but when it's practically 0 effort to do, I'd do it unless there's a good reason otherwise.
Perhaps a better question to ask is why don't you want to follow that convention? If there's no real reason, there's no harm in following it!
The main aim is to guarantee uniqueness of package names, but if you're never going to release code for others to use then it probably doesn't matter, but there is a lot to be said for sticking with convention and worrying about the stuff that does matter. Otherwise come the day that you realise you have a great library that you want to share you could be kicking yourself for going against the flow.
Yes, it is sensible to always use a naming scheme. As a counter-example, assume that everyone would use the default package for their classes.
Common classes like User or Address would be used by several libraries, but in the end there can be only one class of a certain name in the runtime environment. (loosely speaking, it is not completely correct.)
In big projects you will likely use many external libraries, like Apache Commons, Google Guava, Spring, Hibernate, Terracotta. It's good that these libraries all use their own namespace, so that their internal classes do not accidentally conflict.

Why friend directive is missing in Java?

I was wondering why Java has been designed without the frienddirective that is available in C++ to allow finer control over which methods and instance variables are available from outside the package in which a class has been defined.
I don't see any practical reason nor any specific drawback, it seems just a design issue but something that wouldn't create any problem if added to the language.
Here are a few reasons off the top of my head:
friend is not required. It is convenient, but not required
friend supports bad design. If one class requires friend access to another, you're doing it wrong. (see above, convenient, not required).
friend breaks encapsulation. Basically, all my privates are belong to me, and that guy over there (my friend).
In general i think it was because of the added cognitive complexity and low number of cases in which it creates an improvement.
I would say that the extremely huge number of lines of java in production at this moment can attest that the friend keyword is not really a big loss :).
Please see #dwb's answer for some more specific reasons.
Only a very naive and inexperienced programmer would advocate against friends. Of course it can be misused, but so can public data, yet that capability is provided.
Contrary to popular opinion, here are many cases, in particular for infrastructure capabilities, where friend access leads to BETTER design, not worse design. Encapsulation is often violated when a method is FORCED to be made public when it really shouldn't be, but we are left with no choice because Java does not support friends.
In addition to the aforementioned package visibility, Java also offers inner and anonymous classes which are not only friends by default, but also automatically have a reference to the containing class. Since creating such helper classes is probably the only reasonable way to use friend in C++, Java doesn't need it since it has another mechanism for that. Iterators are a very good example of this.
Completely agree with spaceghost's statement in his answer
Contrary to popular opinion, here are many cases, in particular for infrastructure capabilities, where friend access leads to BETTER design, not worse design.
My example is simple - if a class A has to provide a special "friend" interface to class B in java we have to place them into the same package. No exceptions. In that case if A is a friend of B and B is a friend of C, A has to be a friend of C which isn't always true. This "friendship transitivity" breaks encapsulation more then any problems which C++ friendship could lead to.
Why not simply think that Java requires friend classes to be co-located ? The package-private visibility allows everyone from the same package to access those members. So you're not only limited to explicitly declared friends, but you allow any (existing or future) friend to alter some members that are specifically designed for this purpose (but not your private stuff). You're still able to fully rely on encapsulation.
Just to add to the other answers:
There is the default package visibility in Java. So, you could call all classes in the same package neighbors. In that case you have explicit control of what you show to the neighbors - just members with package visibility.
So, it's not really a friend but can be similar. And yes, this too leads to bad design...
In my opinion some kind of friend feature (not necessarily very similar to C++'s) would be very helpful in some situations in Java. Currently we have package private/default access hacks to allow collaboration between tightly coupled classes in the same package (String and StringBuffer for instance), but this opens the private implementation interface up to the whole package. Between packages we have evil reflection hacks which causes a whole host of problems.
There is a bit of an additional complication in does this in Java. C++ ignores access restrictions whilst resolving function overloads (and similar) - if a program compiles #define private public shouldn't do anything. Java (mostly) discards non-accessible members. If friendship needs to be taken into account then the resolution is more complicated and less obvious.

Is having only one class in a package a code smell?

Is it a bad practice to have a package with only one class in it? Would it make more sense just to move the single class to a util package that would contain other random useful classes?
Is it a bad practice to have a package with only one class in it?
Not necessarily. It could be a sign of somebody getting obsessed with classifying things. On the other hand, it could just be a logical consequence of a sensible general classification scheme applied in an unusual case.
An example of the latter might be where you have a general API, and multiple implementations of that API, where each of the implementations consists of multiple classes. But one of those implementations (lets call it the Null implementation) consists of just one class.
The real test is whether the package structure is serving its purpose(s):
Is it making it easier to find library classes?
Do the packages organize the application classes along the lines of the application's logical module structure?
Does the structure allow you to effectively make use of "package private" visibility?
Would it make more sense just to move the single class to a util package that would contain other random useful classes?
Not necessarily. If the class is just another "randomly useful" leaf class, then there is a good case for moving it. On the other hand, if it has a specific function and is not intended to be used generally, then it may be better to leave it where it is.
It is best not to get too obsessed with creating elegant package hierarchies, or with rejigging them when they turn out to be not as elegant (or useful) as you first thought. There are usually more important things to do, like implementing functionality, writing tests, writing documentation and so on.
No
Package is used to put similar classes together,
In your system if there is no similar class then obviously you can put it .
Is it a bad practice to have a package with only one class in it?
Not necessarily. Packages are using to group together logically related entities. It doesn't prevent you from having just one such entity in a package.
Would it make more sense just to move the single class to a util package that would contain other random useful classes?
Not to me, for two reasons:
Util has a specific meaning. Moving an arbitrary entity to util for reasons of loneliness would be a borderline case of util-abuse.
This is premature organization. With Java the IDE support is rich enough to reorganize easily and effectively using a few clicks. Wait a while to see how your project evolves and then take a call.
There are different stategies for static util classes. I use this one :
if your util class is generic (String utils, DB utils, etc.), I put it in a "util" package, that is used in all the application.
if the util class is specific to a domain, I call it "DomainHelper" by convention, and put it in the domain package, at the same level as domain classes.
Yes, it's a definite code smell.
This doesn't mean it's necessarily wrong, but there should be a really good reason for a lone class in a package.
Most instances of a package with a single class that I've seen have been erroneous.
Packages should implement features. It's rare that a feature is implemented using only a single class.
Its not 'bad' to have a single class in a package, Create a new package to group more than one related classes and in case if you expect more related classes to your present single logically unrelated class in future to avoid refactoring. Moving all the random utility type classes to a single package is a common practice seen in many places.Its a matter of choice really.
I guess it depends. It is quite rare in to have a package with one class in it because in addition to the answers listed above, packages also serve the purpose of creating a layered system. A package with only one class in it indicates that the decomposition of the system has not surfaced some objects in the system. So, yes, I would take a closer look at this package and question what the purpose is.
It is better not to stick random stuff in an Util package precisely because of the reason mentioned above. You should ask yourself whether you would think to look in Util for your class in the future before putting it there. When Util grows large it starts to get difficult finding the Utility one is looking for.

designing Java interfaces with ordinary-sounding names, that "play nicely" with other packages

I'd like to define an interface called Tag in a Java package I am working on, but am hesitant to use such an ordinary-sounding name because of the collision issue. (e.g. you can import only one class or interface with a particular name; if there are more than one that share the same name, you can use import for one of them, but the rest you have to explicitly refer to with the entire package name e.g. com.yoyodyne.games.outdoors.Tag)
I also don't really have a more detailed name for it (it's supposed to represent a tag like the tags in StackOverflow posts or other online websites); the closest I can think of is maybe TaxonomyTag.
Are there strategies for dealing with this? The only one I can think of is to define a static class (like Collections) that contains a public interface Tag, e.g. if I call it Taxonomy then I can import Taxonomy and refer to Tag as Taxonomy.Tag -- but that doesn't sound much more helpful.
edit: one widely-known example of this collision is ca.odell.glazedlists.matchers.Matcher and java.util.regex.Matcher which is a pain if you are trying to use regular expressions with the GlazedLists library.
I don't see a problem with naming the class Tag. Your package name makes it universally unique and that is one of the purposes of packages - to resolve naming conflicts.
Even within the Java API there are multiple classes with the same name: java.util.Date, java.sql.Date for example. If you need both in your code then use the fully qualified name.
How many people are going to be using this class? If it's meant to be a general purpose library, I would go with a less-generic name to avoid collisions. If it's just you, and you really don't bite the bullet and go with fully-qualified names for now.
If it becomes a problem before you release the package, just refactor it to a new name.
In similar situations I have found some alternate name for short class names because I hate using FQNs. Even something like JasonSTag can work as a temporary fix; just don't release it that way. Often halfway through implementation I'll find a better way to describe the class, something more descriptive than "Tag".
Are you being lazy? If your class is using imports such that "Tag" could be misconstrued by someone reading your code, even momentarily, then it is worthwhile to think of a better name, despite the package naming convention. Don't underestimate the power of naming---or renaming as the class changes.
I wouldn't really be concerned with this.
What you should be concerned with is how well your class/interface name matches what the piece of code actually does. If Tag succinctly describes what the class/interface does and/or is meant to model, then I think it is a great name.
I can't really see the situation where you'd be using this Tag type in the same class along with other Tag types declared in different packages. But, if you have to, then it's not really that much of a pain to refer to the other Tag types by their fully qualified name.
I believe that how well you named something is greater than making things convenient.
The best strategy is to write classes which do one thing well. These classes do need the minimum of imports, so you have the reduction of import statements.
I looked for standard Tag interfaces; found one in java.swing..html, another one deep in servlet API, and another in tapestry library. I am sure that your class should not directly use one of these (or similar APIs), so you may not be afraid of namespace pollution.
Other solution is to prefix tag with the object it will be used on. E.g. ArticleTag. But you must carefully choose the object name. Or, anyway, you can always refactor it later.
Generally the number of conflicts, even with "ordinary" sounding names, is low. I'd chose a meaningful name within the context of the package.
Do not do somethiong "silly" like prefix it with the company name, eg: YoYoDyneTag.
It has gone out of style to use adjectives/adverbs as interface names recently, however, in your case it wouldn't sound that bad if you used 'Tagable' or 'TaxonomyTagable'.
This only tend to be a problem if you need to use more than one class with the same name in a single class. Examples: java.awt.List and java.util.List, java.util.Date and java.sql.Date.
If you stay away from those already used in the standard Java runtime you will most likely not have a problem.
Whatever you do - make the name you choose a good and descriptive one - this goes especially for those in a public API. You will live with them forever.

Categories