I'm trying to learn some basics of Java and Spring. Recently I came across some beginner project and one of the first steps was to create a Spring Initializr thanks to its website, where everything is clear to me. The next step was to create a basic package structure in the project: model, controller, repository, config, service.
Could someone explain me what exactly is meant by creating these packages after creating a new project? I tried to look up the information myself, but unfortunately I couldn't find an answer anywhere.
I will start by recommending reading about Packages in Java.
In a nutshell, packages are folders. They are used for storing (mainly) classes, but other entities can be stored in packages as well. For example, text files, pictures, etc. In Java, there is no hard set rule that state that only classes must be stored in packages. That said, this is typically not the way projects are structured.
One of the most important functions of packages is to provide namespace for classes. Consider two classes named Table. One is a table containing data and the other is a table used to put stuff on top of; for example a dining table. This means that Table will have to different meanings. Operating Systems will not allow for two files with the same name to exist in the same folder. Therefore, you need to put them in two folders (packages). In the code, you can break ambiguity by declaring the objects using the class' fully-qualified name. For example,
myproject.furniture.Table diningTable = new myproject.furniture.Table();
myproject.data.Table dataTable = new myproject.data.Table dataTable();
There is also access protection with packages by using default access modifier (no modifier). For example:
package myproject
class PackagePrivateClass {
// class contents omitted
}
Notice that this class is not public. In Java, this means that this class is visible to other classes in the same package only. Not even classes in sub-packages will have access.
In summary, packages provide namespace, physical organization, and access protection.
The second thing you should be familiarized with is the best practices with regards to naming your packages. Organizations tend to have packages structured with the domain first, then the main system the code is part of, then subsystems, etc. Before providing examples, here is an article about Package Naming from Oracle.
java.awt => Contains all of the classes for creating user interfaces and for painting graphics and images. AWT stands for Abstract Window Toolkit
When you see the package name, it gives developers and idea what type of classes can be found inside. This will help looking for functions when you are not familiarized with the API (which in turn will help you learning the API much faster). Imagine how hard would be to learn Java if all classes were in the same folder. Imagine how hard will be to figure out what the project does if meaningful names are not used. In the example above, it is kind of easy to figure how what to expect out of classes in the java.awt package.
I was hoping to give you more examples, but I am out of time. Maybe later I will return and write more about this.
Package is nothing but a group of classes. You want to categorize your classes basis their respective purposes. If it's just for self-learning, your package structure should be like
org.novak.sample.service.*
This package should contain all Services, not anything else.
Related
I'm doing a library. I have three packages:
Spreadsheet is the main package. The io package is an internal package for internal use. Unfortunately, the user can access to them since they are public classes.
I would like to keep this package, since it allows me to separate concepts while programming, but i would like to "hide" these classes to the end user.
What could i do?
It's good that you're asking yourself this question! I don't see much attention on this lately.
As OdsReader and OdsWriter are used only inside the Spreadsheet class, just move them inside the spreadsheet package, removing the public visibility keywork. They'll now be accessible only from the spreadsheed package's classes.
The solution proposed above, which is over-complicated for your use-case, and which is to use Java 9+ modules (or OSGi - please no!), is not really necessary here, but it's neverthless a step forward in maintaining definitions private and sealed, even to Reflection abusers.
As a side note, I see you've got an exceptions package.
I never recommend doing so, as you'll have to expose those exceptions' constructor to the users of your code, and they'll be able to instantiate them for no good reasons.
Move the exceptions inside the packages which uses them, and declare the constructor as package private.
Starting with java9, you can turn this library into a module. See this jigsaw tutorial.
Modules need to export a package in order for its public members to be accessible from other modules: Simply don't export your internal package, and it won't be visible.
You can also go with something like OSGi, a module system that predates java9. It too has this notion that there's a level beyond public (let's call it 'visible').
A final option is to use classloader shenanigans (where you for example rename your class files to some other extension during the build phase, and have a small bootstrapper in your visible package which creates a classloader that loads classes by looking in the same place as the visible API, and then load files with the alternative extension, and defineClass those into being), but that's a drastic step that introduces quite a bit of headache. I wouldn't take it unless you have excellent reasons to go down this rabbit hole.
I've been reading a lot about package-by-feature naming convention. So I've decided to give it a try in a new project. However, I'm not sure how it should be named my packages that will be used by most of my classes, since I'm using a huge framework, such as Spring and Hibernate, for example.
This is how handle our Spring contexts classes:
And our database access class, the one that manages connections and so on.
I've a draft about this: using a common package for these frameworks, like:
com.company.project.common.spring
com.company.project.common.database
But I'm afraid that this still looks like package-by-layer a bit. :)
How the packages that will be accessed by my feature classes should be created ?
The common recommendation is "package by feature, not layer". What I often do is "package by feature, then layer". I also think that top-level packages should be "feature"-based (functional components, whatever). But I also like to have my layers separated into sub-packages.
From my point of view, framework-related code does not per se constitute "features" (as in "important, high-level aspects of the problem domain"), therefore package-by-feature is does not make much sense here. But still, this is important code and you need an approach to structure it.
I am normally use two approaches:
If I need to extend or augment libraries I'm using, I structure packages parallel to the package structure of the library. For instance if I'd need to implement some new number formatter for Spring, I'll probably name the package com.acme.foo.springframework.format.number, parallel to org.springframework.format.number.
However if I need to implement common base classes for layers of features, this would be probably something like com.acme.foo.common.<layer>. For instance if we have com.acme.foo.<feature>.dataaccess packages for data access layer of some feature, com.acme.foo.common.dataaccess could hold base classes for data access layers of all features.
Both approaches are used in parallel. You just have to decide whether some class is a framework or library extension (can you imagine using it outside this project?) or is it closer to the layers of your project.
I am wondering if there is a way around this problem without changing the package structures.
I have 2 similar web apps with identical package structures. Classes are the named the same as well.
I would like to use both versions of these packages and create objects from the classes in a third app.
The reason for this and as an example, is that I want to create a single web app that manages user accounts for these 2 other web apps. The package structure for both is com/mycompany/User.java
The problem (as I see it) is that I can't just have these 2 apps package structures in my classpath and have a way to differentiate between them when creating objects.
i.e.
When creating a User object, how can I specify that I want to create it from package 1 or package 2. I don't want to refactor the code or change the way the apps packages are structured.
you can't do this, in java a class its identified by his package and his name, you cannot have two classes in the same package with the same name.
In fact its really a very bad practice, why you have two things with exact the same name representing two different things?. Change your package an include the application name, at least, in the name:
com/mycompany/myapplication/User.java
You could possibly use 2 classloaders loading from different .jar files (for a sophisticated solution check out OSGi). But it's going to be very confusing, and I would recommend renaming/repackaging.
You cannot do that in any recommended way.
You should refactor it.
If there is no chance of refactoing, e.g for legal reasons, then try this approach:
Although I will not recommend it, you could use Proguard to obfuscate only the class User, and use a predefined obfuscation.map and name it there User2.
The output is a new jar file, where the class User has a new name.
Example of such an obfuscation.map entry:
com.company.transform.TransformException -> ad.d:
For our assignment we need to write code for a neural network. The way I planned to do it was to write a Node class, which is a node within the network; a Layer class, which is a layer of nodes and a NeuralNet class, which is a network of layers.
I'm having a lot of trouble understanding the way Java is designed to work for imports. To me it seems that it should be a simple matter to include my Node class in my Layer class, and my Layer class in my NeuralNet class, however Java doesn't like importing from the default package.
What I have read suggests that anything you import needs to be in a package and packages have their own subdirectory. Because of the way I plan to structure my classes, this leaves me with what seems to me, an unwieldy and unnecessarily complex directory structure ie.
neuralpkg.layerpkg.nodepkg.Node
Can someone explain to me whether this is the only way to implement the structure that I want or whether there is some much, much simpler way that I've missed?
For what its worth I'd have no trouble writing this in C/C++, but attempting to import in a similar style has only given me heartache.
You don't need to layer the package like neuralpkg.layerpkg.nodepkg, where "neural", "layer", and "node" are subpackages for the respective classes.
You can simply create a package named "ben" and put all of your classes in there. So within your source directory you'd have a layout like:
--/ben
----Layer.java
----NeuralNetwork.java
----Node.java
Each class definition should then start with the line package ben;.
Classes in the same package don't need to import each other.
It's more like this:
Make a directory called src. This is the root under which all java files will go. Underneath it, make a series of directories called
com->ben->neural or some such. Put all your java source files in the neural folder.
Also, what IDE are you using? Score yourself Netbeans, Eclipse, or the free version of IntelliJ. Java needs a good IDE. When you create a new class, the IDE will do the package statement for you and help immensely with the imports.
Think of packages in Java like namespaces in C++. From what it sounds, it seems like you want everything in the same namespace. The default package can sort of be thought of as unnamed namespaces (I think).
What you should do is just create a simple package com.class.hw01 for example. And put all your classes in there. That way you don't even have to import anything, you can just declare/use your classes just like in C++ if they were in the same namespace.
First of all, I know how to build a Java application. But I have always been puzzled about where to put my classes. There are proponents for organizing the packages in a strictly domain oriented fashion, others separate by tier.
I myself have always had problems with
naming,
placing
So,
Where do you put your domain specific constants (and what is the best name for such a class)?
Where do you put classes for stuff which is both infrastructural and domain specific (for instance I have a FileStorageStrategy class, which stores the files either in the database, or alternatively in database)?
Where to put Exceptions?
Are there any standards to which I can refer?
I've really come to like Maven's Standard Directory Layout.
One of the key ideas for me is to have two source roots - one for production code and one for test code like so:
MyProject/src/main/java/com/acme/Widget.java
MyProject/src/test/java/com/acme/WidgetTest.java
(here, both src/main/java and src/test/java are source roots).
Advantages:
Your tests have package (or "default") level access to your classes under test.
You can easily package only your production sources into a JAR by dropping src/test/java as a source root.
One rule of thumb about class placement and packages:
Generally speaking, well structured projects will be free of circular dependencies. Learn when they are bad (and when they are not), and consider a tool like JDepend or SonarJ that will help you eliminate them.
I'm a huge fan of organized sources, so I always create the following directory structure:
/src - for your packages & classes
/test - for unit tests
/docs - for documentation, generated and manually edited
/lib - 3rd party libraries
/etc - unrelated stuff
/bin (or /classes) - compiled classes, output of your compile
/dist - for distribution packages, hopefully auto generated by a build system
In /src I'm using the default Java patterns: Package names starting with your domain (org.yourdomain.yourprojectname) and class names reflecting the OOP aspect you're creating with the class (see the other commenters). Common package names like util, model, view, events are useful, too.
I tend to put constants for a specific topic in an own class, like SessionConstants or ServiceConstants in the same package of the domain classes.
Where I'm working, we're using Maven 2 and we have a pretty nice archetype for our projects. The goal was to obtain a good separation of concerns, thus we defined a project structure using multiple modules (one for each application 'layer'):
- common: common code used by the other layers (e.g., i18n)
- entities: the domain entities
- repositories: this module contains the daos interfaces and implementations
- services-intf: interfaces for the services (e.g, UserService, ...)
- services-impl: implementations of the services (e.g, UserServiceImpl)
- web: everything regarding the web content (e.g., css, jsps, jsf pages, ...)
- ws: web services
Each module has its own dependencies (e.g., repositories could have jpa) and some are project wide (thus they belong in the common module). Dependencies between the different project modules clearly separate things (e.g., the web layer depends on the service layer but doesn't know about the repository layer).
Each module has its own base package, for example if the application package is "com.foo.bar", then we have:
com.foo.bar.common
com.foo.bar.entities
com.foo.bar.repositories
com.foo.bar.services
com.foo.bar.services.impl
...
Each module respects the standard maven project structure:
src\
..main\java
...\resources
..test\java
...\resources
Unit tests for a given layer easily find their place under \src\test... Everything that is domain specific has it's place in the entities module. Now something like a FileStorageStrategy should go into the repositories module, since we don't need to know exactly what the implementation is. In the services layer, we only know the repository interface, we do not care what the specific implementation is (separation of concerns).
There are multiple advantages to this approach:
clear separation of concerns
each module is packageable as a jar (or a war in the case of the web module) and thus allows for easier code reuse (e.g., we could install the module in the maven repository and reuse it in another project)
maximum independence of each part of the project
I know this doesn't answer all your questions, but I think this could put you on the right path and could prove useful to others.
Class names should always be descriptive and self-explanatory. If you have multiple domains of responsibility for your classes then they should probably be refactored.
Likewise for you packages. They should be grouped by domain of responsibility. Every domain has it's own exceptions.
Generally don't sweat it until you get to a point where it is becoming overwhelming and bloated. Then sit down and don't code, just refactor the classes out, compiling regularly to make sure everything works. Then continue as you did before.
Use packages to group related functionality together.
Usually the top of your package tree is your domain name reversed (com.domain.subdomain) to guarantee uniqueness, and then usually there will be a package for your application. Then subdivide that by related area, so your FileStorageStrategy might go in, say, com.domain.subdomain.myapp.storage, and then there might be specific implementations/subclasses/whatever in com.domain.subdomain.myapp.storage.file and com.domain.subdomain.myapp.storage.database. These names can get pretty long, but import keeps them all at the top of files and IDEs can help to manage that as well.
Exceptions usually go in the same package as the classes that throw them, so if you had, say, FileStorageException it would go in the same package as FileStorageStrategy. Likewise an interface defining constants would be in the same package.
There's not really any standard as such, just use common sense, and if it all gets too messy, refactor!
One thing that I found very helpful for unit tests was to have a myApp/src/ and also myApp/test_src/ directories. This way, I can place unit tests in the same packages as the classes they test, and yet I can easily exclude the test cases when I prepare my production installation.
Short answer: draw your system architecture in terms of modules, drawn side-by-side, with each module sliced vertically into layers (e.g. view, model, persistence). Then use a structure like com.mycompany.myapp.somemodule.somelayer, e.g. com.mycompany.myapp.client.view or com.mycompany.myapp.server.model.
Using the top level of packages for application modules, in the old-fashioned computer-science sense of modular programming, ought to be obvious. However, on most of the projects I have worked on we end up forgetting to do that, and end up with a mess of packages without that top-level structure. This anti-pattern usually shows itself as a package for something like 'listeners' or 'actions' that groups otherwise unrelated classes simply because they happen to implement the same interface.
Within a module, or in a small application, use packages for the application layers. Likely packages include things like the following, depending on the architecture:
com.mycompany.myapp.view
com.mycompany.myapp.model
com.mycompany.myapp.services
com.mycompany.myapp.rules
com.mycompany.myapp.persistence (or 'dao' for data access layer)
com.mycompany.myapp.util (beware of this being used as if it were 'misc')
Within each of these layers, it is natural to group classes by type if there are a lot. A common anti-pattern here is to unnecessarily introduce too many packages and levels of sub-package so that there are only a few classes in each package.
I think keep it simple and don't over think it. Don't over abstract and layer too much. Just keep it neat, and as it grows, refactoring it is trivial. One of the best features of IDEs is refactoring, so why not make use of it and save you brain power for solving problems that are related to your app, rather then meta issues like code organisation.
One thing I've done in the past - if I'm extending a class I'll try and follow their conventions. For example, when working with the Spring Framework, I'll have my MVC Controller classes in a package called com.mydomain.myapp.web.servlet.mvc
If I'm not extending something I just go with what is simplest. com.mydomain.domain for Domain Objects (although if you have a ton of domain objects this package could get a bit unwieldy).
For domain specific constants, I actually put them as public constants in the most related class. For example, if I have a "Member" class and have a maximum member name length constant, I put it in the Member class. Some shops make a separate Constants class but I don't see the value in lumping unrelated numbers and strings into a single class. I've seen some other shops try to solve this problem by creating SEPARATE Constants classes, but that just seems like a waste of time and the result is too confusing. Using this setup, a large project with multiple developers will be duplicating constants all over the place.
I like break my classes down into packages that are related to each other.
For example:
Model For database related calls
View Classes that deal with what you see
Control Core functionality classes
Util Any misc. classes that are used (typically static functions)
etc.