From: Sir Robert Burbridge<[email protected]>
To: The elegant MVC web framework<[email protected]>
Sent: Mon, 22 November, 2010 17:20:16
Subject: Re: [Catalyst] Begginer's question about application structure

I use DBIx::Class with multiple interfaces in the same app; this is the
structure I've found most useful so far:

     ### the lib dir.
     lib/

     ### MyApp stores everything relevant to my app
     lib/MyApp

     ### "MyApp::Web" stores the web interface
     lib/MyApp/Web
     lib/MyApp/Web/Model
     lib/MyApp/Web/View
     lib/MyApp/Web/Controller

     ### HTML::FormHandler forms that are web-specific.
     lib/MyApp/Web/Form

     ### Stores db stuff for DBIx::Class.
     lib/MyApp/Schema/

     ### Normal DBIx::Class schema, results, and resultsets
     lib/MyApp/Schema/MyApp
     lib/MyApp/Schema/MyApp/Result
     lib/MyApp/Schema/MyApp/ResultSet

     ### Schema/Result and Schema/ResultSet contain things like Moose roles
     ### that I want to apply to multiple models, but that really only make
     ### sense in the context of this application.
     lib/MyApp/Schema/Result
     lib/MyApp/Schema/ResultSet

     ### A namespace for script based access to the app
     lib/MyApp/Script
     lib/MyApp/Script/User
     lib/MyApp/Script/User/Create.pm
     lib/MyApp/Script/Report
     lib/MyApp/Script/Report/Documentation.pm

     ### Libs specific to the CLI
     lib/MyApp/CLI

     ### Tests
     t

     ### Store
     t/lib

A couple of notes:

The contents of lib/MyApp/Script are scripts that use MooseX::GetOpt.  I
added a helper script in script/myapp_utils.pl that allows me to do this
(this is mock output, but you get the idea).  In the example below, it
scans through the following namespaces in order:  MyApp::Script,
$ENV{MYAPP_SCRIPT_NAMESPACE}, CatalystX::Script, Catalyst::Script;
looking for ::Schema::Loader.

     ### Run with no arguments
     $ ./script/myapp_utils.pl
     Available scripts:

        Report::Testing
        Report::Documentation
        Schema::Loader
        User::Create
        User::Modify
        ...

     $ ./script/myapp_utils.pl Schema::Loader
     An error has occurred: Required option missing: username
     usage: myapp_utils.pl [-?bdnpu] [long options...]
          -? --usage --help          Prints this usage information.
          -u --usr --user --username  A username with which to log into
     the db
          -p --pwd --pass --password  A password with which to log into
     the db
          -b --db --dsn              The DSN of the source database (e.g.
     "dbi:mysql:myapp")
          -d --dir --directory       a directory into which to install
     the schema
          -n --namespace             the path to a directory

     $ ./script/myapp_utils.pl Schema::Loader \
     --user      ogopogo                      \
     --pass      vonmugwumpus                 \
     --dsn       dbi:mysql:my_db              \
     --dir       lib                          \
     --namespace MyApp::Schema::MyApp

     Creating schema ... done.

     $

Web forms are stored in the path like Halifax::Web::Form::CD::Create
(create a new CD from the script interface).

FWIW =)

-Sir
Hi,

Thanks for taking the time to put this information together.  There is some very
useful advice and ideas in there which I will take on board.  MooseX::GetOpt
looks very handy, and it's this sort of information - the tips and tricks of the
professionals if you like - that really help to advance the skills and knowledge
of others.


Regards,

Martin





_______________________________________________
List: [email protected]
Listinfo: http://lists.scsys.co.uk/cgi-bin/mailman/listinfo/catalyst
Searchable archive: http://www.mail-archive.com/[email protected]/
Dev site: http://dev.catalyst.perl.org/
You're welcome =)

By the way, I forgot to mention one piece of practical advice when determining what should be in your controller vs. model:

_/*Write your controller first.*/_

The controller acts as a functional specification for your models; it's a "live test", so to speak. So if you've got an Artist-CD sort of setup, use this process:

1) Figure out your URI schema (do you want /cd/928420249292/artists or /cd?id=928420249292&field=artists, or what?) 2) Once you figure out that you want /cd/928420249292/artists ;) write the controllers. This is very important: /Write the controllers as though the models already exist, then implement models to the controllers/. Write your controllers as though it's a perfect world, and your ideal models exist. That means do things like:

   sub some_controller :Path :Args {
   ### Task:  sell 10 copies of a CD to a customer.
      $cd = $c->stash->{cd};
      $customer = $c->user;

      ### We could do the following:
      ###
      ###   my $quantity = 10;
      ###
      ###   ### Adjust the stock levels in the store
      ### $c->stash(remaining_stock => $cd->remaining_stock - $quantity);
      ###   $cd->popularity($cd->popularity + $quantity);
      ###
      ###   ### Record in the customer's data that he purchased this
   quantity
      ###   ### of this CD
      ###   $customer->log_purchase(item => $cd, quantity => $quantity);
      ###
      ###   ### ... and so on.
      ###
      ### but why?  That may appear clean simply because we've wrapped
   things up in
      ### methods, but those will *always* be done when we purchase
   CDs; the cashier
      ### at the store shouldn't have to do that manually.  We could
   just wrap all
      ### that activity up into the concept of "purchasing":
      $customer->purchase($cd => 10);
   }

When your entire feature is added in the front-end, then go to your model and implement to spec.

   package MyApp::Schema::MyApp::Result::Customer;
   ### ...

   sub purchase {
      my ($self, $item, $quantity) = @_;
      ### Do all the stuff involved in purchasing an item here.
   }


-Sir
























_______________________________________________
List: [email protected]
Listinfo: http://lists.scsys.co.uk/cgi-bin/mailman/listinfo/catalyst
Searchable archive: http://www.mail-archive.com/[email protected]/
Dev site: http://dev.catalyst.perl.org/

Reply via email to