1.4-Software-Development-Principles

Packages

Learning goals

Introduction

In Java packages are used to organise classes, interfaces and other code-elements. This helps clarify the “namespace” by avoiding naming conflicts, but is also improves access control using access modifiers. Additionally, using packages, improves the modular development of your programs. Classes and interfaces that are related are grouped together to improve maintanance and reusability.

Naming conventions for packages

Proper use of packages

Organisation

Well designed packages contain classes and interfaces that are logically related. For instance a package called com.myapp.ui would the the place for all classes that build the user interface for my application.

Below you can find two examples of an application that uses packages to logically group classes.

Example 1: the Desktopapplication

Below is the package structure for a simple desktop application that manages notes:

com.myapp

├── main // Entry point of the application
   └── Main.java

├── models // Contains classes representing data models or entities
   ├── Note.java
   └── User.java

├── utilities // Utilities used across the application
   ├── FileUtils.java
   └── DateUtils.java

├── controllers // Logic for handling user actions and updating the view
   ├── NoteController.java
   └── UserController.java

└── views // Contains classes related to the user interface
    ├── MainFrame.java
    ├── NoteView.java
    └── LoginView.java

This structure clearly divides the application in clear components.

For beginning programmers (and rather small projects) it is important to start with a simple structure. As your experience, and your project, grows, you can introduce additional sub-packages.

Example 2: the Webapplication

Below you will find a more detailed package-structure for an imaginary webapplication:

com.myapp

├── main // Entry point of the application
   └── Main.java

├── models // Contains classes representing data models or entities
   ├── User.java
   ├── Product.java
   └── Order.java

├── dao // Data Access Object layer for database interactions
   ├── UserDao.java
   ├── ProductDao.java
   └── OrderDao.java

├── services // Contains business logic
   ├── UserService.java
   ├── ProductService.java
   └── OrderService.java

├── controllers // Handles incoming web requests and sends responses
   ├── UserController.java
   ├── ProductController.java
   └── OrderController.java

├── utils // Utilities and helpers
   ├── DatabaseConnection.java
   ├── Logger.java
   └── ValidationUtils.java

├── config // Configuration files and startup configurations
   ├── AppConfig.java
   └── DatabaseConfig.java

└── web // Web-specific classes like filters, listeners, etc.
    ├── filters
       ├── AuthenticationFilter.java
       └── LoggingFilter.java
    ├── listeners
       └── AppContextListener.java
    └── servlets
        ├── LoginServlet.java
        └── LogoutServlet.java

This structure offers a division into additional responsibilities:

Avoiding name conflicts.

Packages allow you to define classes with a name that also exists elsewhere in another part of you program, or in different programs, because the complete name of your class includes the entire package name. For instance: java.util.Date and java.sql.Date are two very different classes, but your program can easily use both.

Access control

Packages works closely together with the access modifiers (public, protected, private, and default (no modifier)) to control access to classes, methods and variables.

Good or bad reasons for using packages

Using packages in Java is crucial for keeping things organised, maintainable, and accessable. Below we have some examples of good and bad reasons for using packages that show the problems that might be caused.

Organisation

Grouping classes based on their functionality into a logically named package, for instance:

No organisation

Placing all classes into a single package, or a package without a clear function will be problematic for larger projects:

Consistent naming

Using the reverse domainname for packages to guarantee uniqueness like nl.saxion.sdp.project.module This helpt identify the likely maker of this project and their website. This works worldwide and allows your library to be used by others.

Inconsistent naming

Just as with method and variables, giving a package a useful name is essential, try to think of the goal for which a package exists. Additionally, bad naming conventions, make it difficult to understand the relation between packages. Mixing languages is of course strongly discouraged, as well as numbering: com.myapp.data1, com.myapp.data2.

Making everything public

Just making all your methods public may lead to breaking encapsulation. This allows users to make changes in a way that you did not intend. It also confuses the user on how to use your classes. Which methods are important? And which aren’t? It also generates more dependencies between classes since users can now depend on access to internal implementation details.

Using the default package

When a class is defined without a package declaration, then this class is not a part of any package. In that case we say that it is part of the “default package”. Classes from the default package can never be imported into other classes. Access control works different for the default packages as well. Finally, it breaks your organisational structure.

In other words. Always place a class in a package.