I learned spring and its layered structure(controller,service and dao)
@Controller("userController")
@service("userService")
@Transactional( propagation = Propagation.REQUIRED, isolation = Isolation.DEFAULT, readOnly = true)
@Repository("userDAO")
Now I am confused how do I make use of good OOPS practices (like this) with these layered structure to make a big project( real world have more complex business logic then sample applications usually provided). I also want to use these spring transaction and other features provided by framework.
Can some please help me out with it or refer to open source project which clarifies my doubt.
In nutshell
Layered architecture will just ease the code maintainability and consistence when it becomes huge and complex.
The fact to remember is that to do a proper software design before doing the implementation.
- Encapsulation - Business logic specific for a domain model should go inside it.
- Abstraction - Segregate the interfaces according to the grouping of services while writing the common business logic in the abstraction.
- Inheritance - Use when you are drafting your domain objects
- Polymorphism - Along with inheritance when you want to change the business logic of child models.
In detail
Below I'm trying my best to provide an example of an ERP application for this discussion. Hope an ERP is a sufficient big project to view the business logic complexity.
The below description is for any developer who need an idea to understand and make use of layered project structure in Spring (or any other framework).
But please note these are not rules to be followed but the best practices to be utilized. :)
1. Data Access Layer - Model /Domain Objects
This contains the mapping of actual tables to classes.
In an ERP example, this is where you get the models: CustomerOrder
, CustomerOrderLine
This also contains the en-capsuled logic of child domain objects and the domain logic of self. For example, the CustomerOrderLine
is a child of CustomerOrder
. The child cannot exists without the parent. So the parent will have the full control of building the childs within it. ie Business logic encapsulation.. ie: Add CustomerOrderLine
, RemoveCustomerOrderLine
etc.. And when it comes to self domain logic, ApproveCustomerOrder
, RejectCustomerOrder
etc..
2. Data Access Layer - Repository
This contains nothing but simple CRUD to database with SELECT, INSERT, UPDATE and DELETE SQLs
. You can use repository pattern in Spring along with Spring Data JPA
.
Key note: do not write any complex logic in this layer unless your logic is highly data intensive
In that case you might have to write one or more functions to do complex query statements. (Preferably in JPQL
)
In an ERP example, this is the place you write logic for GetCustomerOrders
, GetCustomerOrderByCustomer
, GetCustomerOrderLines
, GetOrderByStatus
In simple terms this layer defines how the application will communicate with the outside entities such as Database.
3. Service Layer
This is the place where you should put your complex business logic which involved Multiple unconnected (not child - parent) domain models. These will be reused in Web Controllers and Rest API Controllers.
So to maintain the consistence and to implement the security, I would prefer all the business logic even which were written in the domain models gets wrapped up at this layer.
In the ERP exmple this is the place you write the logic or wrap the logic which is written in Domain Model. For example CreateCustomerOrder
, ListCustomerOrder
, ApproveCustomerOrderLine
, ReleaseCustomerOrder
,...
In case if these logic should get executed along with other model logics, then those should be called at sequence within service layer as well. For example.
Misc Examples on complex business logic
If you want to create a Purchase Order
for your supplier, when the Customer Order
is released.
Then, this can be done by creating a service called SupplyChainService
binded using Spring AOP to the CustomerOrderService.ReleaseCustomerOrder
.
4. Controllers
Controllers can be categorized in two, namely: Web Controllers, and REST Controllers. No business logic should be implemented in this layer because the same logic can be required to call in Web as well as in API level.
In the ERP system, this is the place where you will write the controller for your customer order form to enter data and save it to create a new customer order.
This will be the place you will also create a API controller like REST to create the customer order via a mobile application or from a windows client.
Thanks to the SO community who showed me areas that I didn't cover on OOP principles in this answer
Spring application design and OOD are not mutually exclusive.
The typical Spring (MVC) application has the following structure:
- One or more
@Controller
classes. These are the entry points of your application. They should not contain any business logic. Despite the name I identify them as the V in MVC (Model-View-Controller)
- One or more
@Service
classes. This is where you develop your business logic (BL). One of the benefit in putting your BL here is that it can be reused by multiple controllers (by a @Controller
and by a @RestController
for example). They are the C in MVC.
- One or more
@Repository
classes, where you implement your persistence layer (database, in-memory, whatever...). Additionally you can implement a set of @Component
s classes that describe your domain objects. These are the M in MVC.
- Other classes that you can't map in the MVC pattern, like
@Configuration
, @ControllerAdvice
and other Spring configuration/management classes.
While designing each of these objects, you can follow whatever OOD approach you like.
In the OOD example you mentioned, I would design my application like this:
- One view (
@Controller
) for each actor
- One
@Service
for each use case
- One
@Repository
and one @Component
for each domain class
EDIT: you can find an example project I wrote for university here. It implements what I explained in the last three points with an additional layer (between @Controller and @Service) because there was a requirement to minimize dependencies on the C layer. The concepts still apply.
You are trying to understand two different concepts that can interoperate together.
Layered Architecture
Layer architecture is one of the architecture styles of the industry. In this we have separate layer to do specific logic. Example we have presentation layer, business layer and data service layer. This is called horizontal slicing of the application. There are other architectural styles like Service Oriented/Component based architecture where the application is sliced vertically.
Lets suppose you have automated reservation process. Normally if you go with the layered architecture design (horizontal slicing) then we have different layer to do the job required. But when it comes to the vertical slicing then we identify different entities of the application as Reservation, Customer Management, Fund Management. We will implement these components and they intercommunicate to build our reservation application. The point to remember here is internal component can fallow the same layered architecture.
OOPS Concepts
OOPS concepts helps you design the application in the object oriented manner. Once you identified the architecture style then you have to implemented the application in an extendable manner that can be easily maintained. So, they different implementation methodologies . OOPS is on of them. It suggest some of the design principles that helps you to implement the applications in a better way
See SOLID
I think, you are asking a wrong question here. Layered architecture is inherently not object-oriented, and therefore, while using (some of) the object-oriented practices with it would be possible or even advisable, it should not by itself be the goal. It is akin to asking how do I use best truck driving practices to ride a bike.
Why am I saying that layered architecture is not object oriented? Well, as we know, there are three principles that distinguish object-oriented design: encapsulation, inheritance and polymorphism.
While the last two may or may not be present, depending on your design choices, layered architecture is, pretty much, the opposite of encapsulation: by nature of this approach, you explicitly separate your data ("DTOs") from your logic ("services").
Don't get me wrong, the fact that this approach isn't object-oriented doesn't mean that there is anything wrong with it. And vice versa, "object-oriented" isn't synonymous with "good", it's one of many tools in a programmer's toolbox, and, as with any tool, is better suited to solving some problems than others.
Layered architecture is a good design pattern, that can be successfully used to solve many real-life engineering problems. It has it's own set of best practices that can and should be used, and while that set may have some intersections with its counterpart from OOP, the two are certainly not equivalent.