in reply to Re^6: Trying to understand Catalyst::Model::Adaptor
in thread Trying to understand Catalyst::Model::Adaptor

Me personally? Nope :) Generally the only case I'd agree it would be best to skip the model is the case where the code will only ever be used once in a single Controller. Forever and ever. I could see that sort of functionality being in several Controllers and methods (though if you do write something like that use Path::Class::File->new(path)->slurp or something similar instead of invoking shell commands). These lines-

use NonCatalyst::FileCat; my $fc = NonCatalyst::FileCat->new($c->config->{file_directory}); my $file_name = $c->request->params->{file}; $c->stash->{result} = $fc->cat($file_name);

-become-

$c->stash->{result} = $c->model("FileCat")->cat($c->request->params- +>{file});

Granted you have cost yourself up front with setting up the adaptor and configuration for the model. But it really is trivial effort and it allows you to change the file_directory in config related to the functionality -- Model::FileCat -> file_directory: /some/place -- instead of in the "global" app config. Theoretical win but better namespacing nevertheless.

I'm not trying to preach; thinking in MVC instead of scriptese is a really good way to save yourself misery over time. I wish someone had hit me with this particular cluebat much earlier. Your own use case and preference matters, of course. Do what thou wilt.

Replies are listed 'Best First'.
Re^8: Trying to understand Catalyst::Model::Adaptor
by tospo (Hermit) on Apr 08, 2010 at 08:48 UTC

    OKOK, forget the actual file reading - it was just an example of a simple model that needs a little bit of configuration (the directory) and a parameter to spit out some result.

    I still don't quite get what's wrong with using this in several controllers. the model is completely separated from the controller and if I need to make a change to the way I read files (i.e. use something more sensible than backticks in this case...), I still only change the model, i.e. my NonCatalyst::FileCat module in a single place. How would the adaptor approach help me with that?

    It seems to me that the only benefit of using an Adaptor is that the model has access to the config. I can see the point for that if the model needs a lot of configuration and is tightly tied in with the Catalyst App but if it simply requires a directory to work with or some other trivial data, then it seems that I get much better separation of web app implementation and back-end model by using the NonCatalyst class directly. The way I suggested, I can just as easily use the model class from a command line script or a desktop GUI app or something.

    Apologies for being so persistent :-) and thanks a lot for your patience. It's just that this seems so counterintuitive to me and I can imagine that others have the same questions. I like Catalyst so far but there is not as much information out there as for some other web frameworks.

      I can just as easily use the model class from a command line script or a desktop GUI app or something.

      Quick definition clarification: if it's not in Cat, it's not a Model. It's unrelated code like any other piece of Perl. Model means it's bound to the app regardless of what is underneath. You can bind any code that provides data or services as a Model. The Adaptor stuff is precisely to do that: glue so that you don't have to duplicate external code or write code from scratch to bind it into your app.

      I'll start to sound like a broken record soon. This is the summation of the issues we've discussed + a new one about testing I should have mentioned already-

      • Excepting setup you will end up with 2-5 times as much code and much of it boilerplate, violating DRY and increasing the likelihood of bugs sneaking in.
      • You might change FileCat to the new and improved FileCat2 at some point. With the Model you now have one line of code to edit instead of possibly dozens or even hundreds.
      • This reeks of code smell-
        # APPLICATION ------------------------------------------------- name: "OH HAI" default_view: "TT" default_model: "DBIC" file_directory: "some:/place/else"
      • This doesn't-
        # MODELS ------------------------------------------------------- Model::FileCat: args: file_directory: "some:/place/else"
      • You will never conceptually separate your code from your data and your presentation. You will think exclusively in "scriptese." You will continue to give traditional, inline code preference over strict adherence to the MVC. Dogs and cats, living together.
      • You cannot unit test (as flexibly) without the Model; with a Model, you can reset the Model to whatever you want via config: mock, test fixtures, etc; with hardcoded modules, you may have to resort to contortions to test things. This means you are drastically less likely to test. This means FAIL. :(

      This is Perl. Do it the way you want to do it. Just like life, though, a little discipline up front, even when it seems unecessary, can repay greatly down the road in unforseen ways. I'm not the MVC cop so this is really just advice but I've been doing this almost 12 years now and Catalyst for 5 and the advice is good. :)

      Google for "catalyst model" and read some of the blog posts, tutorials, and list threads. You'll get, one hopes, a deeper feel for things than from the plain Pod. The new Catalyst book ISBN 9781430223658 is also quite worth getting.