Reputation: 8111
After reading https://softwareengineering.stackexchange.com/questions/165444/where-to-put-business-logic-in-mvc-design/165446#165446, I am still confused as to where I want to put my code for computing discounts. Computing a discounted price for a product or service I think is definitely part of business logic and is not part of application routing or database interaction. With that, I am struggling where to place my business logic.
Example
class Model
{
public function saveService($options)
{
$serviceId = $options['service_id'];
//Model reads "line Item" from database
$service = $this->entityManager->find('Entity\ServiceLineItem', $serviceId);
//uses the data to compute discount
//but wait.. shouldn't model do CRUD only?
//shouldn't this computation be in Controller?
$discount = ($service->getUnitPrice() * 0.25);
// Add the line item
$item = new SalesItem();
$item->setDiscount($discount);
}
}
class Controller
{
function save()
{
$this->model->saveService($options);
}
}
Question:
Above $discount
computation, should it stay in Model, or does it go into Controller? If it goes into Controller, Controller has to call $service
(via Model) first, then compute $discount
inside Controller then send it the value back to the Model to be saved. Is that the way to do it?
Note
I may be confusing Model with "Storage". I probably need to have a Model where I do business logic and Database/Persistent Storage should be a separate layer.
Upvotes: 1
Views: 3063
Reputation: 1090
The Below Image shows how I think where your "Business" logic should go :)
The above image has the "Service" layer as the Server Side "Controller".
It is the middle man between the "Client" side Controller and the "Logic" layer.
All of your tasks that requires some type of "Logic" like
"Computing a discounted price for a product or service"
Would go into a ProductLogic Class where it takes inputs From the Service if needed and uses that information to help calculate the discounted price.
The ProductLogic Class will also query a "Data" source if needed to get the current price of an item.
The ProductLogic Class will piece together the information it collected from the Service and Repository to make the calculation and if it needs to be return to the user then the ProductLogic class will send it to the Service layer.
If it just needs to be saved in the Repository than the Logic will pass off the information to the Repository to handle.
Hope this helps :)
Have a great day!
Upvotes: 0
Reputation: 1418
Business logic belongs in a Service, so you would need to add a service layer.
Business logic tends to span multiple models, which infers that it does not belong in any single model. Therefore, it is unclear in which model you should put the logic.
Enter the service class.
I tend to make a service for each use-case the software is designed for.
In your case there could be a CheckOutService
which would calculate your total sum, including discounts.
That way each service has a specific and intuitive purpose. Then, when a controller requires some business logic, it calls a service tailored for that very purpose.
A good description of what a service does in the MVC pattern can be found here: MVCS - Model View Controller Service
I'll quote the most essential part:
The service layer would then be responsible for:
- Retreiving and creating your 'Model' from various data sources (or data access objects).
- Updating values across various repositories/resources.
- Performing application specific logic and manipulations, etc.
edit: I just saw kayess answer. I'd say his answer is more precise than mine, but I don't know how relatable it is, given the degree of uncertainty in your question. So I hope mine can help some people in the earlier stages of their programming career.
Upvotes: 6
Reputation: 3394
Answering a question like this is usually opinionated or one could say it really depends on your business use case.
First off, i sense some mixup in your Model
and service
wording here.
A model
should be your domain model
, and service
should either be a domain
or an application service
, in a different class or a different layer.
Architecturally thinking you could follow a rather simplified DDD
-ish implementation.
Namely:
To achieve a cleaner architecture and less pain by maintaing your code in the longer run, don't forget to think about how design patterns and SOLID principles could help you implement your solution to the given business use case.
Upvotes: 3
Reputation: 1399
The question about how to separate business logic from data is not easily answered. However, Daniel Rocco has constructed a good discussion of the subject that you may find helpful, if not for this particular problem, then for structuring business applications in general.
Upvotes: 1
Reputation: 1282
I used a framework called "Yii Framework" using MVC, what it had was a function called beforeSave() in the controllers that was used to change the model values just before saving them.
Following this logic maybe the best practice would be to apply the discount to your price just before saving the model (in your Controller)
Upvotes: 0