Packages with classes grouped by type, are like utility classes. This may not always be what you want.
Packages are something we usually don’t give much thought. For that reason developers sometimes just use them to group classes together, for example classes that perform similar actions or share a common ancestor. I think packages can offer a lot more than just grouping similar classes and should be thought of as an OOP (Object Oriented Programming) concept. Thats why I say: “Packages are like classes”. Now let’s investigate what other possibilities of organizing code are available with packages, and how that relates to classes.
Like I said before, I consider packages an OOP concept, just like inheritance and delegates. Using packages as such will help you design better libraries and apps, because using these features will help you to hide the implementation details, clients don't need to know about. (Clients being any code using your code, even in the same app)
Before diving deeper into this, let’s discuss how we organize code and how we use access modifiers to determine what methods should be visible. The first building block is code. Your application consists of code. This code is grouped into methods. These methods are grouped into classes and the classes, in turn, are grouped into packages. And finally we use access modifiers to control the visibility of these methods. By doing so we can make them internal to the class or to their subclasses. Or private within the package. Package private is like protected, except that the methods and fields are not available to subclasses (in other packages). The full access table looks like this:
Now think about this for a moment, think how you usually use these various modifiers to hide certain methods from external clients or subclasses. Think about how private methods contain very specific implementation details you dont want a client to use.
Now imagine, that you can also use these modifiers on your classes, as members of your package. Now think about grouping classes in a package “because they are all fragments or activities” or “because they are all helpers”. Think about them as if they were methods of a class, which ones would you like your clients to use, and which ones would you like to hide.
When you group your classes by type, you lose package private, and thereby the option to minimize the visibility of these classes. You cant hide your implementation details because the class needs to be accessible from other packages as well, for example to create an instance.
Grouping by type
So what packaging by type really brings is the same thing static utility classes bring. They allow you to group a set of classes together. You can see this for example in Javas collections framework. Most of the implementations are intentionally grouped in the java.util package. This is intentional because they are all supposed to be used by any client that needs them.
So spreading your implementation details over multiple packages leaks your implementation details to the
client. If you are creating a library this is even worse. These implementation details are now part of
your public API. You need to maintain it, and make sure it is keeps working for all consumers of your
library. People will also start using it in ways you never intended and are going to start reporting
bugs on those use-cases. So next time you create a class, specifically for a single feature, think
whether it is something that should be public or package private. And remember, you can always refactor
your code if you are not satisfied with the result.