I am confused about the structure of creating service layer and DAO layer:
in some examples I see some people creating interface+implementation for both service and DAO and in other examples I see people creating implementation only specially when the DAOs extends an AbstractDao class that contains generic methods for those DAOs, so I am confused about what to go for, why to go for this solution or the other one, and what is the best practise (commonly used) please advise.
I suggest to create interfaces for service and for DAO. Very often you would like to mock service in unit tests of code, that use this serice.
Also Spring, for example, forces you to use interfaces when you are using some Spring proxies for example for transactions. So you should have an interface for service.
DAO is more internal part, but I always try to use interfaces for them to simplify testing.
I prefer interface + implementations for the following reasons:
Interfaces becomes contracts: they tell you what is available to call, and you never worry about the implementation thereof, provided that the result is expected.
You can create customizable implementation of the interface without breaking other implementations of the same interface (generally useful when writing unit test). Customizing an implemented only class can bring more error than you don't notice easily.
It creates a framework that can be documented.
Implemented subclasses are used to create the business/application logic that conforms to the interface contract.
I have only done the implementations of service layer, didn't bother with interfaces (except where I had to). I probably should get around to writing the interfaces, but no problems so far. I am doing unit testing just fine without mocking the service layer.
Also, I don't have a DAO layer, as I am using hibernate and it seemed overkill. A lot of my reasoning is based on this blog, eloquently written by Bozho.
I think it is quite debatable (whether to have DAO and hibernate), however I am quite happy with my decision, I pass in thick domain objects and then just make a call to the hibernate session. Each method on the dao layer would literally only be one line (session.persist(mObject), or similar).
One argument I heard against it was a dao layer would make it easier to change/remove orm at a later date. I am not sure if the time spent coding the dao layer in the first place added to the time coding the change, would be less than coding the change without dao layer on its own. I have never had to change ORM technology any where I worked so its a small risk.
From my point of view when you say Service you should have interfaces and if you can't provide or will not provide that, then you don't have the contract between the service and the consumer and it's not a service anymore, you can call it anything else
The interface+implementation is used in order to have loose coupling. You have the flexibility of changing or switching implementations easily without major changes in code.
Think of a scenario where you are using Hibernate for persistence(DAO Layer) and you need to switch to JPA or iBatis or any other ORM for that matter.
If you are using interfaces, you can simply write an implementation specific to JPA and "plug" it in place of Hibernate. The service code remains the same.
Another argument for interface+implementation model is that proxies for interfaces are supported by Java itself while creating proxies for implementations requires using library such as cglib. And this proxies are necessary for transaction support etc.
Check out my post about "fastcode" an eclipse-spring plugin that generates the service layer off your DAO's. Works like a charm.
generate service /dao layer for GWT/Spring/Hibernate/PostgreSQL
Related
When creating a entity with the Jhipster helper, it asks
? Do you want to use separate service class for your business logic? (Use arrow keys)
> No, the REST controller should use the repository directly
Yes, generate a separate service class
Yes, generate a separate service interface and implementation
In which case should I use which option?
What are the benefits and flaws of each solution?
Is it possible to change easily the architecture once everything is set?
IMHO it depends on how complex your application is going to be and how long you plan on having to maintain it.
If your domain model is quite simple and your REST controllers are straightforward CRUD operations without complex mapping, you can get away without using a separate service layer.
If your domain model or interactions get more complex, you might need a 'Separation of Concerns': your Controller classes should just map REST calls from/to the correct DTO's for the REST API, and business logic and coordination between different entities should go in a service class that does not have anything to do with the REST API. In the long term, that makes it easier to make changes in the REST API separate from changes in the business logic.
Some blog posts to read:
https://www.petrikainulainen.net/software-development/design/understanding-spring-web-application-architecture-the-classic-way/
https://blog.cleancoder.com/uncle-bob/2012/08/13/the-clean-architecture.html
Then about the decision to use interfaces or not. The main advantages of using interfaces used to be that it allowed better testing and avoided coupling modules too close. But since 2010, there has been a lot of discussion whether it's worth the overhead. Maybe start reading the discussion underneath Adam Bien's original post:
https://www.adam-bien.com/roller/abien/entry/service_s_new_serviceimpl_why
There is a pattern of making a DAO interface before DAO implementation. I googled the advantages of this pattern and one striking point was to support multiple databases.
Now, what i could understand is that multiple databases here means different database engines rather than multiple datasources. Obviously multiple datasources should not have affect on how DAO implementations are made out of DAO interface.
My question is what can be the situations where we may need to support multiple database engines catering the same data? Also if such need arises, how will the REST endpoints be managed to support different databases?
Will they be like for e.g. /db1/courses/, /db2/courses ? Do correct me if i have made any wrong assumption or statement in this question.
I just wanted to add my answer to this about beginning Spring development. This is one of the things that initially will not make sense at first. You will end up asking yourself:
There will be only 1 database, so this doesn't make sense why do it?
Why would I define an interface when there will only ever be 1 implementation?
But really neither of these are really why you do this. But it is the convention and pattern and this style is just what people are use to and you will like it better overtime. There are some other reasons too:
Spring Data - this is an alternative to using an entity manager, whereby you only define interfaces and Spring will actually create beans which implement your repository functionality for you.
Design - ensuring you define an interface will help keep your repository a repository.
Easier Mocking - although arguably you can still do this in Spring without needing to define an interface it is still a bit cleaner when you want to replace the implementation with another.
But really it is just the Spring way, people will find it easier to understand your code if you do this.
I came across this situation where I had to check two DBs and get the data. The other DB was a back up one.
So this was the flow.
RestController --> Service --> DBService
--> DB1Repository --> Connect to DB1
--> DB2Repository --> Connect to DB2
We can design as we want, all it matters at the end is that we follow SOLID principles.
Basically the high level components should not depend on the low level components, but both should depend on the abstractions.
Ill pop in here to describe a real world example.
We recently wanted to change out a large production database (Oracle) to a different one (SQL Server).
For different areas of the database, we had different DAO interfaces and implementations. For example, CustomerDAO, AccountsDAO, etc.
For each interace (like CustomerDAO) we had an implementation (CustomerDAOImplOracle).
It was relatively straight forward for us to write SQL Server versions of the DAO's (the SQL syntax and jdbc libraries were of course different) and swap them over with minimal changes to our business logic (the services which use the DAO's).
So, CustomerDAOImplOracle was reimplemented at CustomerDAOImplSQLServer. And so on...
What we learn:
Interfaces provide good abstractiuon and allow for multiple implementations
The DAO layer allows us to "switch out" the database (or its client libraries) if necessary
Hiding implementation details of the database from the business logic reduces coupling and complexity
I'm new to Spring and I'm creating a REST-Service.
I wonder what the Service-Layer is for (#Service).
Currently I encapsulate my DAOs with that Layer.
So for example my PersonController receives a PUT, calls the PersonService which calls the DAO which finally saves the person in my database.
I also saw some examples in the www. (https://howtodoinjava.com/spring/spring-core/how-to-use-spring-component-repository-service-and-controller-annotations/)
I also have read this question here: Is this a good Spring Architecture (include testing)
Do I even need the Services, if it only calls the DAO like:
public void save(Person p) {
personDAO.save(p);
}
?
I don't really see what the advantage of this is. I create classes which actually do nothing... Or is it just a architecture standard because additional business logic will be in this layer too?
Also... when I have several services like personService, familyService, animalService, etc. and they all have some method signatures that are the same and some which aren't... is it useful to use Interfaces here?
When I create Interfaces like: Saveable, Loadable, Deleteable (does this even make sense?) - how do I use them correctly? Do I create a new Interface for every service that extends the Interfaces I desire? Like a PersonServiceInterface that extends Loadable and Deleteable and I implement it in my PersonService?
Thanks in advance!
If you do not feel the need for a service layer, then chances are high your controllers are performing way more business logic than they should.
adding a service layer in between allows for dedicated tests of pure frontend (controller handle request and response wiring only / services handle the business logic/ repositories persist and query the data).
so rule of thumb - it is much easier to have many services handle fractions of your logic than to stuff everything into your controllers
i am not sure what you are trying to solve with the interfaces you introduce - i do not think it makes sense to re-invent the Repository interface on top of your services. If your services only forward to repositories directly then there is no use in having them anyway.
I've been trying to improve the separation of concerns when it comes to applications that access a database (via Hibernate).
On one of the applications I've been using the following approach:
Create services with business logic that have no connection/awareness of the database. They only communicate with GeneralDAO (and with other services);
A GeneralDAO responsible for CRUD/find operations, and with methods that involve more complex database queries.
The problems I see with this approach are:
GeneralDAO slowly becomes a God Object, when your application grows and require lots of specific database queries.
Sometimes the more specific Services become only proxies to the GeneralDAO, since the method is simple and only requires a database query. See example 1.
Example 1: Service is just a proxy
BookService manages things related to books in the Library application. Let's consider 2 methods:
archiveBook(Book)
findByIsbn(String isbn)
In archiveBook(Book) there might be considerable business logic involved - we might imagine this involves calls to:
distributionService.unbox(Book);
archivalBook.archive(Book);
librarianService.informNewBook(Book);
But findByIsbn(String isbn) is a lot more simple: it just needs to execute an SQL call to the database. So in this case I see two options:
Redirect the call to an object that can speak to the database to execute the query. For example generalDAO.findByIsbn(String isbn), that uses a db communication layer (in Hibernate it would use a sessionFactory or EntityManager) to execute the query.
Make that database layer available to the BookService, so that it executes the query itself
Questions/opinions (first number identifies the option above):
1.1. Isn't it strange to have 2 methods with the exact same signature, even if this is done to keep the BookService independent of the database layer (and ORM)?
1.2. How do you suggest avoiding The God anti-pattern? Would you suggest breaking the GeneralDAO into several DAOs depending on what the methods do? In this case, won't we risk needing to inject lots of DAOs into some Services, leading to a Service having too many objects injected into it?
2.1 What do you think of this alternative? Doesn't it break the "separation of concerns" by having the BookService be aware of objects at two different levels of abstraction (the DAO and the sessionFactory/EntityManager)?
3.1. Would you suggest any other approach/pattern/best practise?
Thanks!
1.2. How do you suggest avoiding The God anti-pattern? Would you suggest breaking the GeneralDAO into several DAOs depending on what
the methods do? In this case, won't we risk needing to inject lots of
DAOs into some Services, leading to a Service having too many objects
injected into it?
Generally, a DAO class should handle a specific entity.
If one of your entities require many kinds of queries, you could divide it again into two or more DAOs by grouping them by common concern (for example : reading, writing, selecting on agregates, etc...) as you said.
If you have too many queries and too many DAO, maybe, you should check if you don't write almost the same queries in several methods. It it the case, use specification or Criteria API to allow the client to custom queries by parameters. If the queries are really different, you have various processings. So, using multiple DAOs seems a suitable solution. It avoids increasing the complexity and the rise of god objects.
1.1. Isn't it strange to have 2 methods with the exact same signature, even if this is done to keep the BookService independent of the
database layer (and ORM)?
When you divide you app in logic layers, as you noticed, in some operations, some layers perform only delegation calls to the below layer. So in these cases, it is rather common to have method names which are the same. I would go further : it is a good practice to have the same name if it is just delegation call. Why do we create a variation in the conveyed behavior if they both address the same need?
2.1 What do you think of this alternative? Doesn't it break the "separation of concerns" by having the BookService be aware of objects
at two different levels of abstraction (the DAO and the
sessionFactory/EntityManager)?
BookService depends on DAOs but should not depend on sessionFactory/EntityManager which makes part of the DAO implementation.
BookService calls DAO which uses a sessionFactory/EntityManager.
If necessary, BookService may specify transactional details on itself or on its methods with #Transactional annotation.
3.1. Would you suggest any other approach/pattern/best practice?
As you use Spring, try to rely on the Sping JPA repository (less boiler plate to handle for common cases and extensible class)
Using specification or criteria patterns when you have several variants of some queries.
I have a project implemented in a (flawed) 3-tier architecture. My job is making it more generic so that it would be easy to add a new database into the project.
Concrete: there is a databaseFacade for an SQL database and i have to make it more generic so we can add multiple databases very easy. In this case writing it to a CSV file.
My idea in the database layer was to make a interface where all the methods are defined. Then having the database facade (depending which you want to use) implementing this interface so that it becomes more generic.
Then i have some kind of DBmanager class. This DBmanager class will read out a config file so he knows what database to use. Based on this info he will create an instance of the interface and return this to the application layer.
However this is where I don't know if i'm correct. The application layer now has a DBmanager class (where everything is correctly encapsulated only 1 method is public for returning the facade) and after that the DBfacade.
Any thoughts about the correctness of this? Since I'm having doubts.
I've seen a PHP system (Moodle) use almost exactly this pattern and it works fine. All that happens is that the DB type is specified as a config variable and the concrete DB access class is instantiated as the global DB manager object, providing the facade methods e.g. get_records(), which returns a standardised array of row objects. Arguable whether you would call this facade or adapter, but that's hardly a worry.
I'd say go for it with your current plan. You seem to have decoupled the layers properly and understood the purpose of the patterns. Also, the way your low level (DB) and high level (application controller) components both depend on a single DB facade interface in the middle is a good example of dependency inversion, so bonus points for that! :)
This is the correct approach. One minor quibble is that your DBManager actually follows the Factory pattern, and so should be called DatabaseFacadeFactory, assuming that your facade class is called DatabaseFacade.
As you become more comfortable with Java, check out Spring. It provides a lot of tools and techniques that automatically handle situations such as this, and remove the need for much of the boilerplate code. For more information, see dependency-injection.
To me, it seems legit. I'm not an expert in software architecture yet, but your description describes similar concept in comparison to how JDBC was designed.