Can the term business logic be used to describe:
account roles (admin, end-user, unregistered-user, moderator) that control what data is available to the end user?
If not, can someone give offer a term to describe the above situation, and correct me in exactly what business logic means? How does it differ from business rules? examples? Would you put the Business Logic Layer in the Controller in Rails/RoR?
What you are talking about is Role Based Access Control which is a type of business logic.
Business logic would be the operations that get carried out when Models calls are made. The business logic is in the model, not the controller.
Business Logic is the layer of your application where all the control statement of your application is written.
For example you have a simple application of Selling tickets online. Now when you are developing application you has some logic to be implemented for Selling tickets like date of booking should not be holiday. So this rule that you wont sale tickets for holiday is nothing but a Business logic.
For details see this site
http://en.wikipedia.org/wiki/Business_logic
The basic idea is to keep your controllers as thin as possible. Mostly that means that the controller accepts data from the network, and sets up variables needed in the view, and chooses the view.
The process of determining a role, an admin, etc, is a question to ask of a model... probably something like User, or Role, etc. The logic of how that is determined is in the models. The controller coordinates with this information to select a view or redirect if not allowed, etc.
Sometimes I find myself in a controller, doing a complex query to get a certain set of records. That's a code smell that I need to take that query and make a scope or a method in a model somewhere.
If you find yourself chaining a lot of calls on a model, it's probably time to move it to the model. If you find yourself opening up a lot of records, making decisions, and updating records, it's probably time to move to model.
If it's needed to decide what view to show the user (or whether to show it!), the controller is just fine.
Business Logic to me means anything particular about the business processes that you need to implement in Ruby.
For example, if you have a site where people purchase tickets, you might have a business process that says, "A user can only buy one ticket, until the day of the event, after which he can buy up to 5, if tickets are still available". So you have to write that up in Ruby - it's Ruby code that is implementing a business rule.
In contrast, in the same system, you might have code that splits out a ticket as a PDF. I wouldn't consider that "business logic", because it's not a business workflow rule... yes there's business value in printing tickets as PDF, but it's not about the workflow of how the business processes work (or should work) to enable it to serve its customers better.
Where as that rule about buying only 1 ticket? That's a policy of this particular business, a business rule.
Your example, as #Vinnyq12 pointed out, is more of a Access Control description... which you could say might be a type of business logic, yes.
Related
Maybe this question is a little idiot, because everything can be guaranteed in business layer, but I don't know if I should make an efford to bring this kind of guarantees to the business logic layer.
Example:
I have a business logic in an ASP.NET application that the user only can access the second page of a list of products if he has been logged in. In an ASP.NET application the WebSecurity takes care about users login, so I can't call WebSecurity methods in the business layer. How can I handle with It? Only keep this laws in the UI layer?
Business Logic is a broad term that easily confuses developers to what kind of logic they are talking about. People think that "if its a client requirement then it must be a business logic".
Application Logic - These are the kinds logic that are specifically made for the application. They make sure the application runs smoothly, like filtering out garbage input for example.
UI input validations, like an email should always look like user#domain.com
Application security, login.
Business Logic - These kinds of logic are from the problem domain. These are the real world business rules.
If you can talk about the rules without mentioning the application, then it is a good candidate.
Example
Here is a simple exercise: The following items are validations for the user's age. Find out which one belongs to the application logic or business logic.
Age should always be numeric, and within 1 to 100.
User's age must be 18 or above.
HINT: If the customer is trying to buy beer, the cashier will never ask if the customer's age is a numeric or if it is within the range of 1 to 100.
In the real world, the cashier is part of the business, and enforce the rules. It assumes that that the customer's age is normal, not 1000.
The business does not care if you are authenticated or not. You are
there to do business, that's it
Answer to my little exercise:
Age should always be numeric, and within 1 to 100. - This validation is an application logic. It's the application's job to ensure the quality of the users input. No garbage input.
User's age must be 18 or above. This validation is a business logic. The business assumes that the input is always in correct format or range, all it has to do is check whether you are allowed to buy beer.
sounds like you may need more business logic in your business layer to return information based on some extra parameters like
public List<Products> GetProductList(bool isAuthenticated = false)
{
}
then you can pass in the correct values from the UI based on whether users are logged in or not
Putting WebSecurity calls in your business logic would be wrong, correct. What isn't wrong however is using WebSecurity calls in your controllers.
In the action that deals with paging for your product list, you can check whether or not the user is logged in and redirect them to a login page if they try to view anything other than the first page of products.
This question could well be closed for being open to opinion, as there's more than one way to do what you want. For example, using a custom AuthorizeAttribute.
In a complicated system you may have business logic related to what a user can see in a given context that you want to re-use across your system.
For example, amazon.com offers different prices to different users depending on a bunch of different rules. Those prices have to be shown consistently in search, product detail pages, email ads, etc.
If you're not yet at the place where it makes sense to extract out internal service APIs, where does this kind of user-specific model logic go in Rails-style MVC? It doesn't belong in the Model (requires too much context), but also doesn't belong in the Controller (needs to be re-used across many views in many controllers).
What are the leading design patterns for this type of problem?
I guess such complex decisions should introduce a ProductService into your system with some PricePipeline inside it. When any part of the system requests a list of products, passing some filters, ProductService fetches products from DB, instantiates PricePipeline manager and passes a list of products with their initial, DB-loaded prices to each member of PricePipeline manager.
Some caching is obviously required, but... that's another question, isn't it? ;)
At work last week we had a meeting / presentation about rethinking how we do MVC, based on what's probably a lot of research by our boss and some reading into other SO questions. One takeaway for me was that when people say "separate logic from data" it would probably me more accurate to say "separate logic from your data source". If you do the first, you might fall prey to an anemic domain model. Am I correct in this?
Secondly we learned that MVC doesn't contain your business logic anywhere. This should be in a separate service layer or BLL apart from the web app. Reconciling these two points seems a bit tricky - does a particular piece of logic go with the data objects, as basic OOP principles dictate, or in a separate layer?
Here's a specific example that I need help with right now. I'm pretty convinced that this would belong in the service layer but I still have other questions. Let's say I have some behavior that takes as input multiple different entities of different types. It runs, and then as output, it can modify the input entities, and generate new entities as records. In my case it's for a game, but you could say it's like a transaction. There are multiple people involved, some products, and a receipt generated.
The easy question, where would you put this logic? Is it a separate class that gets instantiated?
The hard question (for me) is who is responsible for calling this code? It would feel wrong to have the controller do it. Or is that exactly its job? What if it doesn't get run on any one particular page, but whenever the user accesses the site after a particular time? Base controller?
In general, how do you decide between "this belongs in my entity class so that it isn't just a pile of getters and setters" and "this belongs in my service layer"? Or am I mixing things up... do the entity classes belong in the service layer?
Let's sort out some terminology first. What you're referring to as the "service layer" is more commonly called the "Domain model", as you say, not to be confused with a MVC model. At the most basic level, the MVC model encapsulates the domain model. How the two interact isn't defined by the pattern itself but the models store states the logical way is to realise there are two different states:
The domain state- in the real world this will more often than not be stored in a database somehow but the domain model should not expose any data source to the MVC model. This allows domain models to retain proper encapsulation. Any logic which mutates or accesses this data should be done here with relevant but abstract accessors for the MVC model to access.
The application state- that is things like "Which record is being edited at the moment?"
To answer your question it really depends on what you are doing with the data. If you're doing any kind of processing then this should be done in the domain model. If you're just fetching collections of data which are needed for display purposes then the MVC model should query the domain model(s) to retrieve the relevant data. The view should then inquire the model for this data.
So to answer your questions:
In thisspecific case: The transaction which processes the data should be inside the domain model. It has direct access to all the relevant data and should just be called with any required parameters. This promotes reusability because it's not directly tied to the MVC model.
Technically, if your controller is accessing the domain model directly it's closer to an MVVM implementation than an MVC one. However, this is not a bad thing, provided your domain models take arguments which aren't tied to domain logic there's not real issue. However a controller should not be constructing a domain object (e.g. creating a user account and passing it to the model). The reason for having the domain model which sits outside the MVC triad is for exactly that: So that it doesn't matter what calls the code, the domain logic is agnostic to the architecture it's running in. This is a good thing. MVC is presentaitonal, sometimes domain logic is just data processing. In regard to "whenever the user accesses the site after a particular time" this is domain logic so should certainly go in the domain model. Where depends on exactly what triggers the event, but in this case it could be part of the login routine or similar.
Indeed. The entities (by which I'm assuming you mean objects which refer to a single domain object, a user, a product, a blog, etc?) will probably not contain much logic themselves as they are mostly data structures. An order may have a "getProducts()" or "getDeliveryAddress()" which fetches related entities but the domain model would do any processing on the data itself.
As a rule of thumb, almost any logic that mutates data or processes data that comes from multiple entities should happen in the domain model. There are two main reasons for this: 1. Reusability, that logic can be reused from anywhere. 2. Encapsulation. Once you start putting this logic inside entities you end up with a situation where domain entities have dependencies on other domain entities. This leads to very brittle code in the real world as you end up with arbitrary rules being introduced at a later date such as "These customers don't have to enter payment details". "This is a corporate customer and they don't have a billing address" if you've modelled your "Order" class to be constructed with dependencies on a set or products a user and a billing address this becomes a larger task than dealing with that at an earlier stage in the domain model.
First, before anyone screams dupe, I had a hard time summarizing it in a simple title. Another title might have been "What is the difference between a domain model and MVC model?" or "What is a model?"
Conceptually, I understand a Model to be the data used by the views and controller. Beyond that, there seems to be a great deal of differing opinions on what makes up the model. What's a domain model, versus an app model, vs a view model, vs a service model, etc..
For example, in a recent question I asked about the repository pattern, I was told point blank that the repository is part of the model. However, I have read other opinions that the model should be seperated from the persistence model and the business logic layer. After all, isn't the Repository pattern supposed to decouple the concrete persistence method from the model? Other people say there is a difference between the Domain model and the MVC model.
Let's take a simple example. The AccountController that is included with the MVC default project. I've read several opinions that the Account code included is of poor design, violates SRP, etc.. etc.. If one were to design a "proper" Membership model for an MVC application, what would that be?
How would you seperate the ASP.NET services (Membership provider, role provider, etc..) from the model? Or would you at all?
The way I see it, the model should be "pure", perhaps with validation logic.. but should be seperate from business rules (other than validation). For example, let's say you have a business rule that says someone must be emailed when a new account is created. That doesn't really belong in the model in my view. So where does it belong?
Anyone care to shed any light on this issue?
The way I have done it - and I'm not saying it is right or wrong, is to have my View and then a model that applies to my view. This model only has what is relevant to my view - including data annotations and validation rules. The controller only houses logic for building the model. I have a service layer which houses all business logic. My controllers call my service layer. Beyond that is my repository layer.
My domain objects are housed separately (in their own project, actually). They have their own data annotations and validation rules. My repository validates the objects in my domain before saving them into the database. Because every object in my domain inherits from a base class which has validation built in, my repository is generic and validates everything (and requires it inherits from the base class).
You might think that having two sets of models is duplication of code, and it is to an extent. But, there are perfectly reasonable instances where the domain object is not appropriate for the view.
Case in point is when working with credit cards - I have to require a cvv when processing a payment, but I cannot store the cvv (it is a $50,000 fine to do so). But, I also want you to be able to edit your credit card - change of address, name, or expiration date. But you aren't going to give me the number or the cvv when editing it, and I certainly am not going to put your credit card number in plain text on the page. My domain has these values required for saving a new credit card because you give them to me, but my edit model doesn't even include the card number or cvv.
Another benefit to so many layers is that if architected correctly, you can use structuremap or another IoC container and swap out pieces without detrimentally affecting your application.
In my opinion, controller code should only be code targeted at the view. Show this, hide that, etc. The service layer should house the business logic for your app. I like having all of it in one place so it's easy to change or tweak a business rule. The repository layer should be relatively dumb - devoid of business logic and only query your data and return your domain objects. By separating the view models from the domain model, you have much more flexibility when it comes to custom validation rules. It also means you don't have to dump every piece of data into your view in hidden fields and push it back and forth between the client and server (or rebuild it on the backend). Your view model will then house only the information relevant to the view - and it can be customized to have bools for view logic or counts or enums so that the view itself isn't cluttered up with complicated logic statements like
<% if (!String.IsNullOrEmpty(Model.SomeObject.SomeProperty) &&
Model.SomeObject.SomeInt == 3 && ...) { %>
While everything seems spread out and over-layered, it has a purpose for being architected this way. Is it perfect? not really. But I do prefer it to some past designs of calling repositories from the controller and having business logic mixed in the controller, repository, and model.
I too often wondered how exactly the MVC elements fit in a traditional web application structure, where you have views (pages), controllers, services, and data objects (model). As you said, there are many versions of that.
I believe the confusion exists because of the above stated, widely accepted architecture, which uses the "anemic domain model" (alleged)-anti pattern. I won't go into much details about the "anti-patternness" of anemic data model (you can look at an effort of mine to explain things here (Java-based, but relevant for any language)). But in short, it means that our model holds only data, and business logic is placed in services/managers.
But let's assume we have domain driven architecture, and our domain objects are the way they are expected to be - having both state and business logic. And in this domain-driven perspective things come into place:
the view is the UI
the controller gathers the inputs of the UI, invokes methods on the model, and sends back a response to the UI
the model is our business components - holding the data, but also having business logic.
I guess that answers your main questions. Things get complicated when we add some more layers, like the repository layer. It is often suggested that it should be invoked by the business logic placed in the model (and hence each domain object has a reference to a repository). In the article of mine that I linked I argue that this is not quite a best practice. And that in fact it is not a bad thing to have a service layer. By the way, domain-driven design does not exclude the service layer, but it is supposed to be 'thin', and only coordinating domain objects (so no business logic there).
For the anemic data model paradigm, which is widely adopted (for good or for bad), the model would be both the service layer and your data objects.
In my opinion,
Model -
Should not contain business logic, it should be pluggable(WCF like scenario). It is used to bind to view so, it should have properties.
Business Logic -
It should be placed at "Domain Services Layer", it is separate layer altogether.
Also, will add one more layer here "Application Services".
App Services talks to Domain Services layer to apply business logic and then lastly return the Model.
So,
Controller will ask Application Service for Model and the flow will go like,
Controller->Application Services(using domain services)->Model
The MVC pattern and the Asp.net framework makes no distinction on what the Model should be.
MS's own examples include persistence classes in the model. Your question about membership being in the model. This depends. Are classes in your model owned by something? Is there a link between who logs in and what data is displayed? Is there filtering of data part of a permissions system that is editable? Is who last updated or edited an object part of your domain as in somebody else needs to see it or something for backend support?
The email example is also it depends. Are you familiar with domain eventing or eventing in particular? Do you have a separate service to send emails? Is the act of sending an email part of your domain or is it a application level concern outside of the scope of your system? Does the UI need to know if an email was sent successfully or not? Do emails that fail to send need retries? Does the content of the email sent need to be stored for support or customer service requirements?
These types of questions are overly broad and subjective but I'm answering so you and everybody who voted you up can understand this.
Your requirements/timelines/resources all bleed into your system's architecture. Even the revenue model can have an effect. You also have to consider the pattern you are shooting for. DDD is much different than persistence-as-model applications and all the slop in between are also valid for certain apps. Are you shooting for testing the app? All of this has an effect.
I'm creating a new ASP.NET MVC application. So far I've used the Account controller for actions related to a user's account -- Login/Logout, Activation (like Register, but I use Register for other actions in the site so I've renamed it), Add/Update Contact information. Up to now, though, I've been concentrating on the administrative user views.
I'm at the point where I'm going to start creating the various views that non-administrative users will see. These are rather limited compared to the administrative interface. My inclination is to create a new set of views and associated controller in the User "family" instead of using the Account views/controller. Is this a good idea or should I stick with the Account controller? My feeling is that since this is for ordinary users it should be a separate controller since Account would apply to both ordinary and administrative users.
EDIT: After reading the first couple of responses, my refactored question is:
Do you consider the Account controller to be for administrative actions related to the user's account or for all actions on the user's account? Would you distinguish between membership/role related views/data and application related views/data to the extent of creating a new controller.
Related, but doesn't directly answer my question: ASP.NET MVC Account Controller usage guidelines?
I don't think there's a right or wrong answer here, so I'll give you my opinion.
Technically, either solution (extending the Account controller or creating a new controller) will work just fine.
So I think this is more a question of how the users perceive the functionality. I think it's a good idea to follow the convention that the URI dictates the controller (or vice versa, if you prefer).
If, for example, you'd like to have the "administrative" actions on a separate path, then that should be a separate controller. You might want to do this, for example, if you use an IIS module for authentication or if it makes your log analysis easier.
On the other hand, it might be the case that the users perceive account functions and administrative functions as part of the same family of actions, except that some users have additional features. If so, then that suggests that should be on the same path in the URI and, hence, part of the same controller.
Summing up, I think this is a question you should ask your user representative instead of folks on this site. :)
Update: Regarding your updated question, I would say that it is fairly natural to put an action for changing a user's password on the Account controller, and that action could be invoked by the user herself, not just an administrator. So I wouldn't presume that the Account controller is strictly for administrative tasks. On the other hand, your example of the fund-raising performance is well outside of the scope of membership-related things, so it is not clear that it belongs on Account, either. I'm still leaning towards, "ask your user representative."
In ASP.NET MVC you will usually create controls based on data types rather than access types. For example:
Instead of 2 /Controllers/UsersControl.cs and /Controllers/Admin/UsersControls.cs it is easier to use one common controller for both admins and regular users - /Controllers/UsersController.cs (by setting different [Authorize] attributes and views).
I would keep existing AccountController.cs for encapsulating account related functionality. And just add new UsersController.cs for the rest Users related functionality (which could have methods like OnlineUsers etc.)