79

I always thought that the business logic has to be in the controller and that the controller, since it is the 'middle' part, stays static and that the model/view have to be capsuled via interfaces. That way you could change the business logic without affecting anything else, program multiple Models (one for each database/type of storage) and a dozens of views (for different platforms for example).

Now I read in this question that you should always put the business logic into the model and that the controller is deeply connected with the view.

To me, that doesn't really make sense and implies that each time I want to have the means of supporting another database/type of storage I've to rewrite my whole model including the business logic.

And if I want another view, I've to rewrite both the view and the controller.

May someone explain why that is or if I went wrong somewhere?

5 Answers 5

79

ElYusubov's answer mostly nails it, domain logic should go into the model and application logic into the controller.

Two clarifications:

  • The term business logic is rather useless here, because it is ambiguous. Business logic is an umbrella term for all logic that business-people care about, separating it from mere technicalities like how to store stuff in a database or how to render it on a screen. Both domain logic ("a valid email address looks like...") and workflows/business processes ("when a user signs up, ask for his/her email address") are considered business logic, with the former clearly belonging in the model and the latter being application logic that goes in the controller.
  • MVC is a pattern for putting stuff on a screen and allowing the user to interact with it, it does not specify storage at all. Most MVC-frameworks are full stack frameworks that go beyond mere MVC and do help you with storing your data, and because the data that should be stored are usually to be found in the model, these frameworks give you convenient ways of storing your model-data in a database, but that has nothing to do with MVC. Ideally, models should be persistence-agnostic and switching to a different type of storage should not affect model-code at all. Full fledged architectures have a persistence layer to handle this.
11
  • 4
    Most MVC-frameworks kind of mix all the storage/database stuff into the model in order to make it easy to store your models (often by making you extend the frameworks model-class). This is probably the source of confusion. Technically, the model-code you write should be the actual model (domain layer), whereas the code provided by the framework should deal with storage (persistence layer). For example, something like User.find(...) (with User being a model) works because the framework implemented the repository pattern as part of the Model.
    – Waquo
    Nov 21, 2012 at 9:29
  • 3
    View-Controller-Model-Storage is the general principle (although the relationship between M, V and C should be visualized as a triangle). When your framework mixes storage into their "model", it works kind of like this: View-Controller-(Model inherits storage from framework).
    – Waquo
    Nov 21, 2012 at 9:48
  • 2
    View-Controller-Model-Storage is rather crude, because it shouldn't be flat. For example, when a controller does something like User.find(...) to get a model, it asks the storage layer directly rather than going through the domain layer.
    – Waquo
    Nov 21, 2012 at 9:54
  • 2
    In architectures with more careful layering, it would be something like UserRepository.find(). By "model" I meant the "model"-class provided by the framework, which you inherit from. The User-object returned by User.find() is a model of a user in the sense that somebody modeled what a user is, how a user behaves...
    – Waquo
    Nov 21, 2012 at 10:34
  • 1
    @flipdoubt business logic is any logic that should be kept the same if you ported from mvc to say a uwp app.
    – Andy
    Oct 9, 2019 at 22:53
28

You and large parts of the programming world seem to misunderstand what the roles of the MVC parts are. In short, they are:

Model = domain logic

View = output logic

Controller = input logic

This means that the model is responsible for the entire business logic: anything that is related to drawing widgets on a screen, driving a printer, outputting data as HTML, parsing HTTP requests, etc. etc. doesn't belong in the model.

However, many of the modern so-called "MVC" frameworks don't really do MVC at all, or they mis-label their parts. Quite often, what is called "model" is the persistence layer of the model, while the business logic sits in what they call the "controller"; the actual controller is usually just a central entry point with a routing table and a bit of code in the individual "controller"s to dispatch the input they receive to the correct business processes. What these frameworks call "view" is really a bit of everything: some presentation logic (View), a bit of input handling and validation (Controller), and some more business logic (Model). The lion's share of the actual view is usually called "templates".

You might also want to read about the Multi-Tier Architecture; where MVC is kind of one-way (the flow is Controller -> Model -> View), Multi-Tier is a two-way thing (Presentation -> Logic -> Data -> Logic -> Presentation), and quite a few frameworks that pretend to do MVC actually do Three-Tier, relabeling Presentation to View, Logic to Controller, and Data to Model.

3
  • 3
    I believe you misrepresent the Model ("Model = domain logic"), to my mind it is more a vessel for population with data, which is then rendered using a View, in the purest form of the MVC pattern. Sure in really simple use cases you can treat it as the "domain logic" but I'd vouch that most systems worth existing would outgrow that very quickly. Better to split "domain logic" out into a separate layer/class, e.g. a service layer.
    – A. Murray
    Oct 10, 2013 at 13:41
  • @A.Murray: Of course the Model doesn't have to be one monolithic blob of code, and separating it out into persistence, data structures, and domain logic does usually make a lot of sense. Still, MVC groups these three concerns together in the Model. In any case, when your controllers and views contain domain logic, it's no longer real MVC.
    – tdammers
    Oct 11, 2013 at 8:46
  • @tdammers, I like the tidiness of your answer and its focus on logic. In your view, where do application concerns like persistence and transaction processing belong? Seems like MVC should be a four letter acronym like MVCS where the S is for service.
    – flipdoubt
    Jan 28, 2018 at 14:19
16

To truly isolate business logic and make it separate from the presentation layer infrastructure, it should be encapsulated by application services. The MVC architecture is a way to implement the presentation layer and it should remain at that scope, delegating all business logic to these application services. Think of view models as adapters between the view and the data that needs to be displayed on and or read. The controller mediates the interaction between view models, views and application services which host the business logic.

Application services implement business use cases and are decoupled from the presentation layer, whether it be MVC or something else. In turn, application services can host transaction scripts or a domain-driven design.

For storage, the application service can reference a repository or any abstraction of a persistence mechanism. Different implementations can be supported by abstracting the data access into an interface. Typically, these abstractions are leaky and are only partially portable across implementations and it is often a futile attempt to attain full portability.

UPDATE

My suggestion is based on the Hexagonal architecture. In a hexagonal architecture, your domain model (business logic) is at the core. This core is encapsulated by application services which act as a facade. Application services are simple classes which have methods corresponding to use cases in your domain. For an in-depth discussion on application services take a look at Services in Domain-Driven Design. The code sample contains a PurchaseOrderService which is an application service for a purchasing domain. (Note that an application service does not imply the use of domain-driven design.)

In a hexagonal architecture, an MVC presentation layer is an adapter between your domain model (business logic) and a GUI. The domain model isn't aware of the presentation layer, but the presentation layer is aware of the domain model.

This solution certainly has moving parts than a solution which places business logic in the controller and you should weigh the drawbacks and benefits. The reason I suggest it is because I prefer to keep business logic decoupled from the presentation layer in order to combat complexity. This becomes more important as the application grows.

3
  • Sounds like you're describing a bastard of MVC and MVVM that has both controllers and view models. Also, I think the architecture you're describing may be a bit heavy for OP's needs.
    – Waquo
    Nov 21, 2012 at 9:05
  • to be honest, I like Waquo's answer more. Mainly because I've no clue what you mean with 'application services'. Could you explain that term? My GoogleFU isn't working here as it seems. Nov 21, 2012 at 9:26
  • 1
    @Waquo I agree that the proposed architecture may be overkill, however it should be considered. I've made no mention of MVVM which is simply another way to implement a presentation layer. Application services apply regardless of whether you use MVC or MVVM and nothing I've suggested indicates any combination of the two.
    – eulerfx
    Nov 21, 2012 at 17:44
1

Depends on what you mean by business logic. Any "logic" that gives meaning to contents of the model should be in the model. In the linked question, the highest voted answer seems to define "business logic" as anything relating to data; this makes sense from the point of view that a business' data is its business!

I once saw an example by the creator of Rails (I think) who was going on about exactly this - not putting "business logic" in the model. His example was a controller class and method for app registration and login - a supplied password in plaintext was encrypted before being inserted into or queried against the model (a database.)

I can't think of a better example of something that is not controller logic and that belongs directly in the model.

The model could be an interface to myriad data stores, alleviating portability concerns. It's here one could find confusion over wether or not the model interface is actually the "controller."

Generally speaking, the controller links the model and view (which are the meat-and-potatoes of the app.) In Cocoa development it can be simplistic to the point where the controller is handled via the XCode GUI (controller objects and bindings.)

The GoF's "Design Patterns" section on MVC, loosely quoted:

The MVC triad of classes is used to build user interfaces in Smalltalk-80. The Model is the application object, the View is its screen presentation, and the Controller defines the way the UI reacts to user input. MVC decouples views and models by establishing a subscribe/notify protocol between them. The following diagram shows a model and three views. We've left out the controllers for simplicity.

MVC is all about UIs. The focus is on the model and view - defining and displaying data. Note the "subscribe/notify protocol" - this is where your controller comes in. You can build all the views you want; so long as they adhere to the protocol you'll never have to touch the model or controller.

If you're talking web development specifically, IMHO many popular web frameworks are fast and loose with the term MVC and its component definitions.

1
  • I'm a C#/Java (only a few projects there) developer. It seems that I misunderstood what the model does. Putting the 'business logic' into the controller really was only a aftereffect (my train of thought went 'okay, I've the model for data (read: database connection/storage), so my business logic needs to get in the controller because I've to apply it before storing the data in the database'. Just have to move everything one level down from the controller. Actually, that solves a problem I currently had (supporting MySQL and MSSQL in one program) Nov 21, 2012 at 9:24
1

Why don't you introduce a service layer?

Then your controller will be lean and more readable, then your all controller functions will be pure actions.

You can decompose business logic as much as you need within the service layer. Code reusability is better and there is no impact on models and repositories.

Not the answer you're looking for? Browse other questions tagged or ask your own question.