Spring directory structure with interfaces (best practices)

Tiberiu :

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
LppEdd :

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)

Guess you like

Origin http://43.154.161.224:23101/article/api/json?id=94102&siteId=1