I'm currently writing my first Spring application (Spring boot + hibernate). I checked the best practices directory structure on their documentation here. It makes sense.
Question 1:
I have an interface
(or Abstract class
) that a few subclasses extend, and so I only need a @Repository
for the parent class. I've decided to do it this way:
com
+- example
+- myapplication
+- Application.java
|
+- message
| +- AbstractMessage.java
| +- IMessageRepository.java
| +- MessageRepositoryImpl.java
+- messageTypeA
| +- messageTypeA.java
| +- messageTypeAService.java
+- messageTypeB
| +- messageTypeB.java
| +- messageTypeBService.java
Question 2:
Now I have a new entity
to save called Group
. So what I could do is add a Group
directory on the same level as Message
. However, this Group
is actually a part of Message
(like, logically), so it would actually make sense if it was part of the same message
directory (the only reason we are saving them as different entities is because it makes more sense to derive analytics that way). Furthermore I'm even using the same MessageRepository
to save it (I just added a second method in the interface like so:)
public interface MessageRepository {
void insert(AbstractMessage message);
void insert(AbstractMessage message, AbstractGroup group);
}
Would something like the following be good? Or should every entity
have its own package? Am I overthinking this?
com
+- example
+- myapplication
+- Application.java
|
+- message
| +- AbstractMessage.java
| +- IMessageRepository.java
| +- MessageRepositoryImpl.java
| +- messageTypeA
| +- messageTypeA.java
| +- messageTypeAService.java
| +- messageTypeB
| +- messageTypeB.java
| +- messageTypeBService.java
|
+- group
+- AbstractGroup.java
+- GroupTypeX.java // same service as message, just different entity
+- GroupTypeY.java // same service as message, just different entity
That's more an opinion-based thing, but I'd like to give you a couple suggestions.
First of all, naming.
The I
prefix on interfaces is an "ancient" technique from IBM to recognize them. Please, don't do that, it's reduntant, it doesn't make sense in a fresh environment. What's an I-MessageRepository
?!
You'll find this kind of naming convention mostly on Eclipse RCP
projects, or any product by IBM.
Then the implementation name. Don't use the Impl
suffix, it does not say anything to the person who is reading or editing your code.
Give it a name which says what its purpose or domain scope is.
ActiveMQMessageRepository
FileMessageRepository
TcpMessageRepository
Second, Repositories
.
Repositories should manage a single type of object, not more than one. Use Services
to coordinate multiple Repositories
. This will make it easier for everyone to debug, and it will decouple a lot of code.
Third, packages
.
Try to always have a flat package structure. A flat structure is easier to maintain, easier to look at, easier to understand. Don't create dozens of sub-packages such as
- messages
- services
MessageService
- implementations
...
- repositories
MessageRepository
- abstract
AbstractMessageRepository
- implementations
TextMessageRepository
- exceptions
- runtime
- checked
UnsupportedMessageException
Horrible and useless. And you cannot leverage package visibility.
So keep messages
and groups
on separate packages, and give them their own Repository
.
Expose interfaces from packages, not concrete implementations. (when possible)