Beefy Boxes and Bandwidth Generously Provided by pair Networks
Just another Perl shrine

Re^2: Help seperating business logic from controller (catalyst/dbic)

by uG (Scribe)
on Sep 09, 2008 at 04:41 UTC ( #709967=note: print w/replies, xml ) Need Help??

in reply to Re: Help seperating business logic from controller (catalyst/dbic)
in thread Help seperating business logic from controller (catalyst/dbic)

<mst> ...everything that's business logic rather than UI flow logic should live in the model. Write methods in your DBIC ->table classes. Use load_namespaces and write methods in your resultset classes. If there's an extra layer of logic that needs to be in front, then -that- should be a model that's exposed to your app. This way everything can be re-used in batch jobs, cron scripts, command line tools, etc...

It was this tidbit that triggered my post. But perhaps i'm just confused with the difference between business and ui flow logic.
  • Comment on Re^2: Help seperating business logic from controller (catalyst/dbic)

Replies are listed 'Best First'.
Re^3: Help seperating business logic from controller (catalyst/dbic)
by perrin (Chancellor) on Sep 09, 2008 at 12:09 UTC

    There are many ways to interpret MVC in a web context. One of them is to say that all of the actual form processing should be handled in some kind of "action" classes, separate from the controller, which you would then say are a part of the model. (Does it make sense to put these in DBIC table classes? Only if the action is reasonably a method of the object type that class is representing. Otherwise, a separate action class makes more sense.)

    Another way to think about it is to say that the "controller" classes in a web framework are already abstract from the web itself and call Catalyst itself the controller and your controller class part of the model. This is a practical point of view and by far the most popular way to do things. However, things like the redirect in your example are obviously web-specific.

    The point of all this is separation of concerns and code reuse. Ask yourself, is there any business logic in here that I might want to use from a non-web context, like a cron job? If I did want to, could I do it?

    In the example you show here, it fails that test. You have rules expressed here (e.g. you can't create a nation with a name that is already taken) which can't be reused outside of this web context. To solve this, you could create a method (maybe in DB::Nation, maybe in Action::NationManager, etc.) which takes the relevant parameters (name, user, etc.) and either returns a new nation or throws an exception. Your controller code calls it and handles the exception by redirecting.

    Sound like a lot of work? It can be. It's definitely worth doing in situations where the code would genuinely be reused, but debatable otherwise. It's up to you to find the sweet spot on the purity <--> practicality continuum for your application.

      This is what I was getting at. Originally I had taken the rule part and did just what you had said, put it in DB::Nation and set it up to handle exceptions. My problem at that point was I wasn't quite sure how to call a method from a Schema file (or to put it in the same namespace). I'll admit i'm pretty lost, but I can't find a good example on how to do this :(
        I don't use DBIx::Class, so I can't help you with the mechanics of that. You could always create a separate action class that isn't part of your DBIx::Class stuff. You also don't have to use all the Catalyst window-dressing like $c->model() if it makes things more confusing for you rather than less.

        Yea, you can put your db/model methods in a ::Schema namespace, but it all comes down to what works best for you. I don't know that you'll hear one consistent method or another, so it's best to use what makes sense to *you*. If it happens to be so far off it's going to cause you trouble, you can certainly have someone in #catalyst do a code review for you and let you know.

        As long as it's reasonably sane, and most importantly, followable by others (and you!), there shouldn't be a problem.

        I have however, separated my model classes into ModelName::TableName for the table definitions and ModelName::TableName::ResultSet for the "most used methods" such as specific searches (getPosts(), getUser() etc.). You have to realize most, if not all, of that is documented in the DBIx::Class::* family. Catalyst has a few pointers, but what you're looking at is strictly DBIx::Class organization/methodology (from what I've read, at least.). It gets convoluted sometimes, but the separation is there to help *you* get to the root of your question and keep logic separate, etc.

        Hope this helps!


Log In?

What's my password?
Create A New User
Node Status?
node history
Node Type: note [id://709967]
and all is quiet...

How do I use this? | Other CB clients
Other Users?
Others having an uproarious good time at the Monastery: (7)
As of 2018-05-22 20:03 GMT
Find Nodes?
    Voting Booth?