[Catalyst] Re: Using model layers between Catalyst and DBIC

Octavian Rasnita orasnita at gmail.com
Tue Feb 7 08:00:09 GMT 2012


Hi Bill,

From: Bill Moseley =

  On Tue, Jan 10, 2012 at 1:18 PM, Jason Galea <lists at eightdegrees.com.au> =
wrote:

    hehe.. you want layers, I got layers..


  I just got out of yet another meeting about this architecture redesign.  =
 (I'd like to see the graph that relates productivity to the number of peop=
le involved some day...)


  Jason, this is probably a question best for you and your experience, but =
I (ignoring that graph above) would like to hear other's opinions and reaso=
ning.




  My goal was to put a layer between Catalyst and DBIC for a few reasons, i=
ncluding:
    1.. To have a place to put common model code that cannot be represented=
 in DBIC (e.g. data from other sources)
    2.. To be able to split up the model into logical units that can be tes=
ted and used independently. =

    3.. To abstract out the physical layout of the database -- be able to c=
hange data layer w/o changing the API.



  I also needed that flexibility for exactly the same reasons, but the "bad=
" thing is that Catalyst does so many things automaticly and DBIC the same =
that it would imply a decrease in productivity if the app would do those th=
ings. ...At least if the app is not very big and complex.

  Some actions, like getting some records from a db, is surely the job of a=
 model, but that model could use records as simple hashrefs (as returned by=
 DBI's fetchrow_hashref), or it could use DBIC records, or other models cou=
ld offer the data with another structure. But there is no standard structur=
e defined for a model that should unify the data from more such models and =
offer it to the view. I guess that it could be hard to define such a struct=
ure because it would differ among different apps and it might also imply a =
performance degradation.

  But some other actions are considered to be the job of the controller, fo=
r example the authentication/authorization, or anyway the job of the web fr=
amework, however sometimes that authentication/authorization should be made=
 in other ways, not by web, but by a simple command line script, or by a GU=
I interface.

  I guess that for beeing able to totally decouple the web interface from t=
he app, that app should offer a certain interface which would be compatible=
 with Catalyst and the developer would just need to configure Catalyst part=
 to handle the app foo at /foo, and another app bar to /bar and another app=
 baz to /.
  And the interface of all those apps should accept an authorization/authen=
tication object with a standard format, and the authentication should be ma=
de by Catalyst or the GUI app, or the CLI script... And the apps used by Ca=
talyst could offer their authentication/authorization and the developer cou=
ld configure Catalyst to use the authentication offered by the app foo, or =
the app bar, or the app baz, or an external authenticator that uses the dat=
abase of another app, authenticator that should do the validation and offer=
 the authentication object in that standard format accepted by the apps.

  This way would be more simple to create adapters for existing apps and co=
mbine them in a single web site, or change the authentication...

  Anyway, the question regarding the common format of the data returned by =
the model to the view remains, and because it could imply performance degra=
ding to change the data structures returned by the underlying modules, it m=
ight not be a good way. I am also thinking that there are many developers t=
hat like the very limited style of other web frameworks which accept a sing=
le ORM, a single templating system and don't even think to decouple the app=
 from the web framework...

  Just thoughts.... Yeah I know, patches welcome. :-)



  My idea was that Catalyst would call a method in the new model layer and =
possibly get a DBIC object back.  There is concern from some at my meeting =
that we don't want to give the Catalyst app developer a "raw" DBIC object a=
nd that we should wrap it (as it appears you are doing, Jason) in yet anoth=
er object.   That is, we want to allow $user->first_name, but not $user->se=
arch_related or $user->delete.


  That requires writing new wrapper classes for every possible result -- no=
t just mirroring DBIC's result classes but possibly many more because the n=
ew model might have multiple calls (with different access levels) for fetch=
ing user data.  That is, $user->email might work for some model methods tha=
t return a user but not methods called on the model.


  Frankly, to me this seems like a lot of code and work and complexity just=
 to prevent another developer from doing something stupid -- which we canno=
t prevent anyway.  And smart programmers can get at whatever they want, reg=
ardless.  Seems more risky to make the code more complex and thus harder to=
 understand.  The cost/benefit ratio just doesn't seem that great.



  **
  Yep, for not allowing the developer to do something stupid, but also for =
making the application not depend so much on the underlying model... DBIC f=
or example.

  So if the team will decide to change DBIC with something else, they shoul=
d be able to continue to use $user->email without changing the controller o=
r the views.

  But in this model of work (using fat models and thin controllers), most o=
f the code is in the model anyway, so no matter if the DBIC model or the bu=
siness model would use the biggest part of the code, changing DBIC with som=
ething else would imply a lot of work if the new underlying module uses a t=
otally different interface than DBIC.

  So it becomes less important if the developer would need to change just a=
 few lines of code in the controller or and/or templates.

  And this is theory, but I am wondering how many times a team decided to c=
hange DBIC with another ORM or another source/destination of data in practi=
ce.
  I guess that if they decide to do that, it would be easier to rewrite the=
 entire application.

  As I shown above, making an app with the interface totally decoupled woul=
d be wonderful but this only if there will be not much performance degradat=
ion which I doubt, and it should be also a standard interface defined for P=
erl programs that should be largely accepted, interface that will allow the=
 developer to choose to publish it with Catalyst, or with another web frame=
work that will accept that interface, but this will be complicated because =
that interface would depend on the app, would be less flexible and might im=
ply performance degradation.



  Am I missing something?




  I suppose this is not unlike the many discussions about what to pass to t=
he view.  Does the controller, for example, fetch a user object and pull th=
e data required for the view into a hash and then pass that to the view?  O=
r does the controller just fetch a user object and pass that directly to th=
e view to decide what needs to display?



  ***
  As its name implies, the controller should control things. So it should d=
ecide what should be presented, not the view. The view should just present =
the data offered by the controller.
  The view should not be able to present something which is not allowed. Bu=
t if many things are allowed, than the controller could offer all those thi=
ngs and don't restrict the user object by creating and offering another obj=
ect which is more limited. The controller should be in control even if that=
 control is very limited sometimes.



  I prefer just passing the object to the view.  The controller code is muc=
h cleaner and then when the view needs to change don't need to also change =
the controller.  And when there's a different view (like an API or moble ) =
the same controller action can be used.




  ***
  Yes, I also prefer that way, because I usually don't need too many restri=
ctions. But sometimes the view should not get too much data, because the vi=
ew could be say a WxPerl app which is in a remote location, and it couldn't=
 receive locally an object and execute methods on it, but it should receive=
 a serialized string, which shouldn't be too big for a faster transfer, and=
 in that case the controller should choose to offer a smaller serialized ob=
ject.

  Octavian
-------------- next part --------------
An HTML attachment was scrubbed...
URL: http://lists.scsys.co.uk/pipermail/catalyst/attachments/20120207/61f28=
6fa/attachment.htm


More information about the Catalyst mailing list