librelist archives

« back to archive

Services Layer in MVC Architecture

Services Layer in MVC Architecture

From:
Calvin Young
Date:
2012-11-15 @ 19:40
This question is more about the MVC pattern in general.  It's not
necessarily related directly to Flask, but I'm curious to hear people's
opinions in the context of developing larger Flask applications.

A common tenet of MVC programming is having fat models with skinny
controllers.  Django and Rails recommend putting all of the business logic
in the models.  But I've encountered plenty business logic that seems
strange to place in the models.  For example:

   1. The logic might involve components that the model shouldn't know
   about (e.g., sending an email to users after they sign up, or uploading an
   image to S3 -- emails and S3 are components that sit outside the
   application data).
   2. The logic might not map to a database model, or it maps to multiple
   database models.  In the case of the latter, I've written plenty of
   business logic that orchestrates operations across multiple models, and
   putting too much of that type of logic in models quickly introduces
   circular dependency issues.

I've read a little about putting business logic in a "Services" layer that
sits between the controller/view and the model:

http://stackoverflow.com/questions/5702391/mvcs-model-view-controller-service

http://stackoverflow.com/questions/2762978/the-purpose-of-a-service-layer-and-asp-net-mvc-2

http://today.java.net/article/2009/11/04/using-service-delegate-avoid-mvc-controller-bloat


The services layer basically acts as an internal API to your application,
and lets you simultaneously avoid fat controllers as well as strange
dependencies in your models.  From a separation of concerns perspective,
this seems like a good idea, but I've only really seen it used in PHP,
.NET, and Java frameworks.

What are the issues with this design, and why hasn't it been adopted in
more modern frameworks such as Django, Rails, and Flask?

Re: [flask] Services Layer in MVC Architecture

From:
Mark Grey
Date:
2012-11-15 @ 19:58
I've had many such cases as you describe and I get what you mean.
 Something doesn't feel right about having SMTP related imports inside your
user model in the create method just to send a one-off email.

I think these kind of cases generally emerge as a "i need to peform this
trivial task within the app environment, and im not sure im going to repeat
it every time" type of thing, which overall is something a framework
designer would want to leave up to you.  What I mean by this is that the
Flask devs don't want to force you to abstract this logic from your models
if that's not what your particular case requires, especially if it's a
one-off task that appears only in one context (because, being honest, in
some of these small apps it almost make more sense to swallow and make that
import than it does to overengineer a separate layer)

What I've gotten into the practice of doing is creating that separate layer
of utility functions within a module in the app package and having the
controller call its logic with any needed arguments coming after the
successful execution of the model method in question (have a
services.send_conf_email called right after a successful user.create, and
maybe a services.register_error or something within its except block.)
 This approach also allows you to include calls to these methods where they
make sense but omit them where they do not (maybe you have an internal tool
that will create new users manually, and you don't necessarily want to call
the email method in that blueprint for internal use)

As for the adoption of something like this in Flask, my impression is that
the Flask devs view it as a microframework.  Its a commonly used term
throughout the docs.  I figure they'd be more inclined to leave this up to
the person building the app rather than enforce a standard given the view
of the framework as such.

On Thu, Nov 15, 2012 at 2:40 PM, Calvin Young <calvinwyoung@gmail.com>wrote:

> This question is more about the MVC pattern in general.  It's not
> necessarily related directly to Flask, but I'm curious to hear people's
> opinions in the context of developing larger Flask applications.
>
> A common tenet of MVC programming is having fat models with skinny
> controllers.  Django and Rails recommend putting all of the business logic
> in the models.  But I've encountered plenty business logic that seems
> strange to place in the models.  For example:
>
>    1. The logic might involve components that the model shouldn't know
>    about (e.g., sending an email to users after they sign up, or uploading an
>    image to S3 -- emails and S3 are components that sit outside the
>    application data).
>    2. The logic might not map to a database model, or it maps to multiple
>    database models.  In the case of the latter, I've written plenty of
>    business logic that orchestrates operations across multiple models, and
>    putting too much of that type of logic in models quickly introduces
>    circular dependency issues.
>
> I've read a little about putting business logic in a "Services" layer that
> sits between the controller/view and the model:
>
>
> http://stackoverflow.com/questions/5702391/mvcs-model-view-controller-service
>
> 
http://stackoverflow.com/questions/2762978/the-purpose-of-a-service-layer-and-asp-net-mvc-2
>
> 
http://today.java.net/article/2009/11/04/using-service-delegate-avoid-mvc-controller-bloat
>
>
> The services layer basically acts as an internal API to your application,
> and lets you simultaneously avoid fat controllers as well as strange
> dependencies in your models.  From a separation of concerns perspective,
> this seems like a good idea, but I've only really seen it used in PHP,
> .NET, and Java frameworks.
>
> What are the issues with this design, and why hasn't it been adopted in
> more modern frameworks such as Django, Rails, and Flask?
>