Re: separating C from V in MVC
[sorry for the broken References - I've just joined the list and am replying to a post in the archives] On Sat, 15 Jun 2002, Perrin Harkins said: An Object-Relational mapper takes objects and stores them in a relational database, as transparently as possible. I think the most pure example of this I've seen in the Perl world is Tangram (www.tangram-persistence.org). SPOPS is also an O-R mapper (actually, its a generic Object persistence mechanism but it seems to most feature-rich when used with an RDBMS). A Relational-Object takes a relational database, and provides access to it (select, insert, update, delete) via objects. Class::DBI, Alzabo, and DBIx::RecordSet are examples of such a beast. I would actually put Class::DBI in with the first set. I'd have to disagree. Maybe Mike had something different in mind when he created Class::DBI, but as the current active developer on it, I'm definitely pushing it in the R-O direction. Like Dave, I always start by thinking of my database schema and then Class::DBI provides a way to translate that, table - class, row - object, column - method. Throw in some simple relationship builders and a sprinking of syntactic sugar, and that's pretty much there is to Class::DBI. To me the difference is not O/R vs R/O, since both of them go both directions. Rather it's a question of what you're modelling in your objects. I think one of the main differences is in what ways you want to be able to manipulate your data. With an R/O approach the Perl classes are just one of the possible views into your data. If you feel like it you can also do your normal SQL type things on it. In fact one of the deliberate strengths of Class::DBI is that you can very easily port an existing roll-your-own-SQL-in-Perl approach over to it gradually. With O/R approaches the object is usually the primary source of the data and the database is just a temporary storage system used for persistence. You probably _could_ go executing arbitrary commands against the database, but it's frowned upon. Things like Tangram model the domain objects, i.e. concerts, seats, people. Things like Alzabo model the database objects, i.e. tables, rows, foreign keys. I think on this front they both try to do both. Class::DBI does anyway. It assumes that you're going to create your database schema in a way that these are fairly much interchangable. Tony
Re: separating C from V in MVC
Tony Bowden wrote: I'd have to disagree. Maybe Mike had something different in mind when he created Class::DBI, but as the current active developer on it, I'm definitely pushing it in the R-O direction. Like Dave, I always start by thinking of my database schema and then Class::DBI provides a way to translate that, table - class, row - object, column - method. Throw in some simple relationship builders and a sprinking of syntactic sugar, and that's pretty much there is to Class::DBI. Tangram may have loftier goals, but in general that's pretty much all there is to any of them. And I don't think that the angle you approach your data design from -- classes or tables -- has much bearing on which tool you would use, with the possible exception of Tangram. SPOPS is explicit about wanting to support legacy schemas without changes. I think that in this realm there is Tangram, which tries to bring some extra stuff like database modelling of object inheritance and queries written in perl, and everything else. Things like Tangram model the domain objects, i.e. concerts, seats, people. Things like Alzabo model the database objects, i.e. tables, rows, foreign keys. I think on this front they both try to do both. Class::DBI does anyway. My casual perusal of the documentation certainly made it look like Class::DBI hid a lot more of the database stuff than Alzabo. After the configuration is done, the database concepts like foreign keys are never explict. I guess my point here is simply that I think there isn't so much difference between most of these tools and that characterizing them as being anti-database or too heavy is not accurate. As a sort of wrap-up to this round of O/R technology discussion, I want to post a link to this quote from the author of SPOPS where he talks about the practical limitations of SQL abstraction. I thought it was a pretty astute observation: http://perlmonks.org/index.pl?node_id=162259 - Perrin
Re: [OT] WebObjects [Was: Re: separating C from V in MVC]
WO is amazing, no two ways about it. Once you use it, everything else sucks. There are no exceptions. That's kind of a rude statement to make on this list, where all of these people are offering free software and support to you. It's been a few years since I last evaluated WebObjects, but it certainly didn't seem like a panacea. It had a number of interesing ideas behind it, but its insistence on trying to hide all the details of the browser interaction made some simple things very hard, especially since it tried to keep all of the state information server-side. The problems it had with back buttons and multiple browser windows come to mind. It also seems to encourage design where browsers directly request a view, rather than calling a controller which chooses a view depending on the outcome of processing. That could be just a shortcoming of their introductory documentation though. - Perrin
Re: separating C from V in MVC
My general motto is tiers eq tears ... I've never seen a really comfortable OO/SQL bridge. So who's talking about an OO/SQL bridge? Not me. At least not an automatic one. I write the SQL by hand. Group bys, order bys, multi-table selects, locking, SQL query plans and index optimisation all rightfully belong to the database but are an anathema to a simple OO/SQL bridge. I use all of those things in my model objects. The model objects use SQL to implement methods like $product-user_comments() or $address-save(), and sometimes it is complex. The point is that the rest of the application gets to the database through the model objects, rather than through SQL. Encapsulation, reuse, blah blah blah. Generally I try to minimise the layers/tiers/abstraction between the front-end and the database - for me OO/SQL abstraction is something akin to 'GOTO considered harmful'. I think you're overgeneralizing based on some kind of O/R mapping tool you've used that tried to do too much. Wrapping up the knowledge of how to work with the database to accomplish certain tasks inside of objects is no different from any other application of OO programming. - Perrin
Re: separating C from V in MVC
This approach works for some things, but I think it falls down when it comes to doing complex database searches, particularly searches generated ad-hoc on multiple columns in multiple tables. In general, the user interface you provide for a search will be much higher-level than the SQL that implements it. That's what is gained by making this kind of object: it's a place to put the translation of the business concept find people in New Jersey into the four table join that might be needed to find them. This is why Alzabo is much lower-level than what you have above. I needed something where I could easily construct queries that might include 1+ tables, with various types of searches of individual columns in those tables (equal to, between, less than, like, etc.) with dynamic sorting (again, on any of the columns in any of the tables, ascending or descending). I would just write SQL at that point, but I do realize that Alzabo provides more database independence. You could easilly use Alzabo to build the queries that implement the model objects I'm talking about. With what you're proposing, I think you could easily end up with either: A) a ridiculously flexible interface that looks sort of like SQL, except where it is SQL, except where it's only sort of like SQL, etc. B) a ridiculous profusion of classes, methods, or both. I think you're overestimating the number of search variations and model objects that most applications have. For example, Fran's application generates his stale watches report. There's no need to create a fully-parameterized search interface to Watch objects just for that. Instead, you make a Watches-find_stale() method or something and keep the knowledge of what that means to the database hidden behind that API. At eToys we had a very large and complex (highly normalized) database, and this approach worked very well. I think it works best when you have a complex database requiring complex SQL, because if you just have a bunch of simple 1-1 table mappings there isn't really much to abstract. I'm thinking of trying out SPOPS the next time I do this kind of thing, because it will automatically handle the no-brainer cases (1-1 mappings) and allow me to write the SQL for the complex cases by hand, all with a consistent interface and hooks for caching, etc. Trying to jam a thick layer of OO-goodness over relational data is asking for a mess. OO has its place, but if your application is primarily about the database, I don't think that a heavy OO layer on top of that will do you much good. There's nothing thick or heavy about the way I do it. There is no automatic SQL generation, and nothing to prevent me from using any SQL tricks that my database supports. It's just a way of wrapping up chunks of code that implement data-related tasks into an easy task-oriented API for the controller (or other model objects) to act on. - Perrin
Re: separating C from V in MVC
An Object-Relational mapper takes objects and stores them in a relational database, as transparently as possible. I think the most pure example of this I've seen in the Perl world is Tangram (www.tangram-persistence.org). SPOPS is also an O-R mapper (actually, its a generic Object persistence mechanism but it seems to most feature-rich when used with an RDBMS). A Relational-Object takes a relational database, and provides access to it (select, insert, update, delete) via objects. Class::DBI, Alzabo, and DBIx::RecordSet are examples of such a beast. I would actually put Class::DBI in with the first set. To me the difference is not O/R vs R/O, since both of them go both directions. Rather it's a question of what you're modelling in your objects. Things like Tangram model the domain objects, i.e. concerts, seats, people. Things like Alzabo model the database objects, i.e. tables, rows, foreign keys. My approach falls in the first camp, although I don't currently use any OOP tools for assistance. - Perrin
Re: [OT] WebObjects [Was: Re: separating C from V in MVC]
Perrin al Once you use it, everything else sucks. There are no exceptions. That's kind of a rude statement to make on this list, where all of these people are offering free software and support to you. Ah, you're right; I actually never meant that as a slight against things mod_perl; I use mod_perl and I support it fervently. But mod_perl WO are at two different places in the stack; WO is a rich framework, mod_perl is an all-powerful skeleton on which we *build* our frameworks. It's been a few years since I last evaluated WebObjects, but it certainly didn't seem like a panacea. It had a number of interesing ideas behind it, but its insistence on trying to hide all the details of the browser interaction made some simple things very hard, especially since it tried to keep all of the state information server-side. The problems it had with back buttons and multiple browser windows come to mind Might have been a problem a long time ago but it's certainly not now. WO supports both its own kind of steroid-enhanced session tracking, which does create problems with back-buttons if you don't use it properly, but it also supports regular mod_perl-style request/response cycles that are perfectly fine with back-button/multiple-window/bookmarking tasks. It also seems to encourage design where browsers directly request a view, rather than calling a controller which chooses a view depending on the outcome of processing. That could be just a shortcoming of their introductory documentation though. Not quite sure what you mean here. The general WO request-response loop is 1 Process request 2 Perform action 3 Return response Step 3 is entirely dependent on the previous two, just like any mod_perl/CGI/php app. WO completely forces division of your C your V and gives you a huge hand in separating your M from either of those. Anyway, sorry if anyone was slighted; I think the most perfect web development env would be a WO-style framework build on top of mod_perl (because who wants to use Java? Jeez) Cheers Kyle Dawkins Central Park Software
Re: [OT] WebObjects [Was: Re: separating C from V in MVC]
Not quite sure what you mean here. The general WO request-response loop is 1 Process request 2 Perform action 3 Return response Step 3 is entirely dependent on the previous two, just like any mod_perl/CGI/php app. The introductory documentation makes it look each URL is tied to a specific HTML template. It may just be a problem with that documentation though. I think the most perfect web development env would be a WO-style framework build on top of mod_perl You can assemble various parts of it from CPAN. Most of the perl O/R frameworks are not as ambitious as EOF, but Tangram is trying pretty hard. The templating tools available for perl are as good as the ones in WO. Using those with one of the MVC frameworks discussed here gets you quite a bit. The main thing you don't get is GUI tools, which there doesn't seem to be much demand for from the mod_perl community. - Perrin
Re: separating C from V in MVC
A) a ridiculously flexible interface that looks sort of like SQL, except where it is SQL, except where it's only sort of like SQL, etc. B) a ridiculous profusion of classes, methods, or both. SQL has its place, and Alzabo merely provides a thin layer on top of it. Trying to jam a thick layer of OO-goodness over relational data is asking for a mess. OO has its place, but if your application is primarily about the database, I don't think that a heavy OO layer on top of that will do HI Dave, Totally agree. My general motto is tiers eq tears ... I've never seen a really comfortable OO/SQL bridge. The OO part almost always dumbs down or hobbles the database. Group bys, order bys, multi-table selects, locking, SQL query plans and index optimisation all rightfully belong to the database but are an anathema to a simple OO/SQL bridge. While disks need to seek and spin ... relational databases will have their place. I sometimes think of a world with unlimited RAM. It's here that OO dreams really come true --- vast pools of objects with hash/array look up speed etc. Until that time though ... I personally code with the database foremost in my mind - and disk seeks a close second - for me the SQL comes first and so I have no problem with large HEREDOCs of SQL in my code. Generally I try to minimise the layers/tiers/abstraction between the front-end and the database - for me OO/SQL abstraction is something akin to 'GOTO considered harmful'. Nige Nigel Hamilton Turbo10 Metasearch Engine email: [EMAIL PROTECTED] tel:+44 (0) 207 987 5460 fax:+44 (0) 207 987 5468 http://turbo10.com Search Deeper. Browse Faster.
Re: separating C from V in MVC
On Fri, 14 Jun 2002, Nigel Hamilton wrote: A) a ridiculously flexible interface that looks sort of like SQL, except where it is SQL, except where it's only sort of like SQL, etc. B) a ridiculous profusion of classes, methods, or both. SQL has its place, and Alzabo merely provides a thin layer on top of it. Trying to jam a thick layer of OO-goodness over relational data is asking for a mess. OO has its place, but if your application is primarily about the database, I don't think that a heavy OO layer on top of that will do HI Dave, Totally agree. My general motto is tiers eq tears ... I've never seen a really comfortable OO/SQL bridge. The OO part almost always dumbs down or hobbles the database. Group bys, order bys, multi-table selects, locking, SQL query plans and index optimisation all rightfully belong to the database but are an anathema to a simple OO/SQL bridge. While disks need to seek and spin ... relational databases will have their place. I sometimes think of a world with unlimited RAM. It's here that OO dreams really come true --- vast pools of objects with hash/array look up speed etc. I feel pretty much the same, and so gave a talk about this (and other things) at last year's perl conference. Slides are at http://axkit.org/docs/presentations/tpc2001/anydbd.axp/a.pdf -- !-- Matt -- :-Get a smart net/:-
Re: separating C from V in MVC
On Fri, 14 Jun 2002, Nigel Hamilton wrote: Generally I try to minimise the layers/tiers/abstraction between the front-end and the database - for me OO/SQL abstraction is something akin to 'GOTO considered harmful'. I think there's room for middle ground here between mapping OO directly to SQL and having SQL in heredocs in your code. What we tend to use is a object that works almost as a SQL factory. We never have SQL directly in our code, but rather all this is placed inside a seperate module.that knows a few things about itself - e,g, what database and table we're using for this run. This can be then used to spit out SQL or run the query and return the results. The key aspect is that anytime you feel you need to write some SQL you should feel free to add more SQL to this module - not limit yourself to waht's already avalible. The advantage of this is that we get better reuse in out of our SQL when we need the same function called from many places, and we can reuse the same SQL on similar tables/databases for different runs. Another advantage is that should we ever want to change the database all our SQL is in a few modules and we can make sure that we change all our SQL. Mark. -- s'' Mark Fowler London.pm Bath.pm http://www.twoshortplanks.com/ [EMAIL PROTECTED] ';use Term'Cap;$t=Tgetent Term'Cap{};print$t-Tputs(cl);for$w(split/ +/ ){for(0..30){$|=print$t-Tgoto(cm,$_,$y). $w;select$k,$k,$k,.03}$y+=2}
Re: separating C from V in MVC
On Fri, 14 Jun 2002 10:34:47 +0100 (BST) Mark Fowler [EMAIL PROTECTED] wrote: : On Fri, 14 Jun 2002, Nigel Hamilton wrote: : : Generally I try to minimise the layers/tiers/abstraction between : the front-end and the database - for me OO/SQL abstraction is something : akin to 'GOTO considered harmful'. : : The advantage of this is that we get better reuse in out of our SQL when : we need the same function called from many places, and we can reuse the : same SQL on similar tables/databases for different runs. Another : advantage is that should we ever want to change the database all our SQL : is in a few modules and we can make sure that we change all our SQL. Another useful thing is that you can implement some cache mechanism there, in one place, and this is transparent to clients who just keep on calling, say, $category_factory-read_category_tree(), no matter whether the tree is actually fetched from the database or from shared memory. -- fxn
Re: separating C from V in MVC
Generally I try to minimise the layers/tiers/abstraction between the front-end and the database - for me OO/SQL abstraction is something akin to 'GOTO considered harmful'. HI Mark, I'm not sure about a monolithic SQL factory module like the one you describe. Generally, each SQL statement is unique so I've never been able to find re-use benefits here. Also passing parameters to SQL Factory methods involves another change of scope/layer which I think is not necessary. In our system, a programmer maintaining the system will look to the object first and find the SQL bang in the middle - which I think has better re-use/maintenance implications than hidden away in a back closet that's packed full of stuff (i.e., all the SQL). One way I minimise the layers between DB and the front-end is to make sure all fields share the same name as in the database - someone has already mentioned this technique. This follows the design tenet - a unit of data should have only one name throughout the entire system. Perl has a great feature: 'slippery typing' (as opposed to Java's strong). This enables me to pass a database row hash - to an object constructor - to a controller - to a view. In my case the view is typically a HTML template holding tokens of the form: {{database-field-name}}. For example, when a search occurs on Turbo10 the following happens: * Engine Object - contains SQL - returns a DBI row hash * Hit Object - is constructed with this DBI row hash * BrowserMessenger Object - formats Hit in Javascript for tranmission to browser using a Template * Template Object - uses the same field names from the DBI row hash to replace tokens In this way, I try to minimise the interfaces going from the database to the browser - and the SQL stays inside the objects that use it. Does anybody else want to confess to something similar? (-; Nigel I think there's room for middle ground here between mapping OO directly to SQL and having SQL in heredocs in your code. What we tend to use is a object that works almost as a SQL factory. We never have SQL directly in our code, but rather all this is placed inside a seperate module.that knows a few things about itself - e,g, what database and table we're using for this run. This can be then used to spit out SQL or run the query and return the results. The key aspect is that anytime you feel you need to write some SQL you should feel free to add more SQL to this module - not limit yourself to waht's already avalible. The advantage of this is that we get better reuse in out of our SQL when we need the same function called from many places, and we can reuse the same SQL on similar tables/databases for different runs. Another advantage is that should we ever want to change the database all our SQL is in a few modules and we can make sure that we change all our SQL. Mark. -- Nigel Hamilton Turbo10 Metasearch Engine email: [EMAIL PROTECTED] tel:+44 (0) 207 987 5460 fax:+44 (0) 207 987 5468 http://turbo10.com Search Deeper. Browse Faster.
O-R mapping vs. R-O mapping (was Re: separating C from V in MVC)
At 12:22 AM -0500 6/14/02, Dave Rolsky wrote: An Object-Relational mapper takes objects and stores them in a relational database, as transparently as possible. I think the most pure example of this I've seen in the Perl world is Tangram (www.tangram-persistence.org). SPOPS is also an O-R mapper (actually, its a generic Object persistence mechanism but it seems to most feature-rich when used with an RDBMS). A Relational-Object takes a relational database, and provides access to it (select, insert, update, delete) via objects. Class::DBI, Alzabo, and DBIx::RecordSet are examples of such a beast. I think what it comes down to is how do you start thinking your project? Well said, Dave. I don't think one approach is strictly better than the other. It depends what you need to accomplish. I wouldn't be surprised to find that the majority of the folks on the modperl list would favor an R-O approach to an O-R one, but that's because probably the vast majority of web apps are primarily about the data. This happens to not be the case for me and I find my O-R mapper to be enormously helpful, exactly what I need most of the time. I'm using ESPOPS, a package built on top of SPOPS to handle objects with inherited attributes spread across multiple tables. Granted, when I do need to fetch my objects based on complicated criteria involving joining of lots of tables, it's not as clean as I'd like. It requires passing SQL fragments into the fetch methods. To me this just means that my O-R mapper has abstracted things nicely to the point where I don't have to touch any SQL 90% of the time, but for those cases where I do need more complicated SQL, it lets me directly at the SQL and doesn't pretend that it's going to be able to do everything I might want. This seems like a good tradeoff to me. One possible improvement (with emphasis on possible) might be to build the O-R mapper on top of something like Alzabo or some other R-O mapper which does a more complete job of abstracting me away from the actual SQL. Then when I want to pass some more explicit query specs through the O-R mapper it would be in Alzabo instead of SQL. My gut feeling is that the extra layer probably wouldn't be worth it. Anyway, my main point is O-R and R-O are different tools for different jobs. A hammer is not better than a saw until you know you're trying to drive a nail as opposed to cut wood. BTW, this thread should probably be moved to the poop list ... -- Ray Zimmerman / e-mail: [EMAIL PROTECTED] / 428-B Phillips Hall Sr Research / phone: (607) 255-9645 / Cornell University Associate / FAX: (815) 377-3932 / Ithaca, NY 14853
Re: separating C from V in MVC
The Pet Shop has a grand total of 13 tables. How well does this approach work with 90 tables? How does it handle arbitrary queries that may join 1-6 tables, with conditionals and sorting of arbitrary complexity? Where I work we have over 90 tables and it works fine. We don't run a ticketing system or a huge e-commerce site but our servers are pretty busy and we have no performance problems. Our application layer does not contain a single line of SQL. The entire system is OO Perl and uses an OR-mapping system that entirely abstracts the tables and relationships between them. It works for us. Maybe it wouldn't for a bigger system, but I would also caution people to say that if you find yourself doing joins across up to 6 tables, you're almost certainly doing something wrong from the start and, basically, you're fooked because of shitty design, and O/R or R/O won't help you. We've found the O/R mapping to be an indispensable part of the system. Since all data is contained in objects, the views/widgets don't need to how the data is populated. They access all data through a single interface. This is how our system works too. Less code, fewer bugs (we hope!), faster development time. For us it's awesome; your mileage may vary. As for people claiming never to have seen an OR system that works, I suggest you check out EOF from NeXT/Apple. That puppy runs banks and insurance companies, and usually without needing a line of SQL. It's not perfect, but it's pretty friggin amazing. Each to his/her own. Kyle Dawkins Central Park Software
[OT] WebObjects [Was: Re: separating C from V in MVC]
At 10:59 AM 6/14/02 -0400, kyle dawkins wrote: As for people claiming never to have seen an OR system that works, I suggest you check out EOF from NeXT/Apple. For those of you (like me) who didn't know what EOF is, it stands for Enterprise Object Framework and is part of Apple's WebObjects app server. Which has moved on to Java, and thus is OT. :-) But I've heard many good things about WebObjects, so it's on my wish list of technologies to investigate. Drew == Drew Taylor | Freelance web development using http://www.drewtaylor.com/ | perl/mod_perl/MySQL/postgresql/DBI mailto:[EMAIL PROTECTED] | Email jobs at drewtaylor.com -- Speakeasy.net: A DSL provider with a clue. Sign up today. http://www.speakeasy.net/refer/29655 ==
Re: [OT] WebObjects [Was: Re: separating C from V in MVC]
Drew is correct, EOF stands for Enterprise Object Framework. However, it's not part of the WebObjects app server... it predates WO by a long time (I think it's about 9 or 10 years old) happens to come with WO but is completely separate from it. On Friday 14 June 2002 11:27, Drew Taylor wrote: For those of you (like me) who didn't know what EOF is, it stands for Enterprise Object Framework and is part of Apple's WebObjects app server. Which has moved on to Java, and thus is OT. :-) But I've heard many good things about WebObjects, so it's on my wish list of technologies to investigate. WO is amazing, no two ways about it. Once you use it, everything else sucks. There are no exceptions. Kyle Dawkins Central Park Software
Re: separating C from V in MVC
On Fri, 14 Jun 2002, kyle dawkins wrote: bigger system, but I would also caution people to say that if you find yourself doing joins across up to 6 tables, you're almost certainly doing something wrong from the start and, basically, you're fooked because of shitty design, and O/R or R/O won't help you. This is one of the sillier statements I've seen on this list. If you have complex data with many entities (and thus many tables) and you have complex queries then you can easily find yourself joining many tables. This is hardly a sign of bad design. In fact, it may be a sign of good (normalized) design. If _all_ of your queries are against 1 table at a time, that seems a lot more worrisome to me (because it suggests insufficient or non-existent normalization). -dave /*== www.urth.org we await the New Sun ==*/
Re: separating C from V in MVC
Fran, I think the key here is taking care of the 80% easily. This has been mentioned in this thread several times, and in previous threads. No, I don't think there will ever be an (efficient) wrapper that can handle ALL the cases and ALL the possible SQL queries. But if you can handle the majority of them easily with a wrapper, and that wrapper also provides a way to get at the SQL directly (I heard SPOPS as being good for this), then that is a lot of work saved. Work saved = money time saved = you look better to your boss. Both approaches have merit, so the trick is to determine which one is best for your situation. At my day job, the tables are relatively denormalized, ie. very wide, so a wrapper can easily work. At a previous job I was working to encapsulate all the SQL calls into a single module. The ability to find the approach that works best for you is the difference between a grunt and a good software engineer. :-) Drew At 01:30 AM 6/14/02 -0400, Fran Fabrizio wrote: I don't typically find apps that just mirror some subset of one of the db tables to be all that interesting. After all, it's the relationships between the data that make the data interesting, and by necessity this means your queries will be complex. And looking over the stuff outlined at poop.sourceforge.net, there's not too many models/frameworks out there that can accurately abstract ALL of SQL, and if it only does a subset, I feel like that's shooting myself in the foot. == Drew Taylor | Freelance web development using http://www.drewtaylor.com/ | perl/mod_perl/MySQL/postgresql/DBI mailto:[EMAIL PROTECTED] | Email jobs at drewtaylor.com -- Speakeasy.net: A DSL provider with a clue. Sign up today. http://www.speakeasy.net/refer/29655 ==
Re: XML vs Perl (Re: separating C from V in MVC)
-BEGIN PGP SIGNED MESSAGE- Hash: SHA1 On Thursday 13 June 2002 6:20 am, Rob Nagler wrote: Matt Sergeant writes: This assumes you need XML in the first place. No, it does not. The rest of my post spoke about XML as a data format and set of tools, not as a syntax. Please stop thinking about XML as syntax!! If my entire system is written in Perl, why do I need XML as a data format? Need is *not* what I said. But anyway, I already said: because of the tools. Perl has nothing that even comes close to SAX as a clean way of doing the unix-like thing of having small tools to do just one job when it comes to data munging. Perl's data structures are richer and have much more support in Perl than XML has in any language. Perl has been around much longer and is full-fledged programming language. It has better tools. It's got a larger community. We disagree on this. You seem to speak as someone who has never tried by the sounds of things. This is one of the things AxKit's XSP taglibs are designed to provide for. I've never used XSP. I have used XSLT, tried to use XSD, and am currently mired in DocBook/XML. One of my sites generates XML for its data export format. Let's take an XSP example from axkit.org: xsp:structure xsp:includeTime::Object/xsp:include /xsp:structure xsp:logic![CDATA[ sub mytime { my ($time) = _; $time ||= time; return Time::Object-new($time); } ]]/xsp:logic Why is the above better than below? (I cleaned up the perl :-) use Time::Object; sub mytime { my ($time) = _; return Time::Object-new($time || time); } Or, why can't I just call Time::Object-new where I need it? Erk. I knew the docs on AxKit.org were going to bite me in the ass one day. This is a really *bad* example of XSP usage. It's not separating content from presentation. Nowadays everything I do uses taglibs, which makes pages look like: wiki xmlns:wiki=http://axkit.org/NS/xsp/wiki/1; wiki:login/ wiki:display-page/ /wiki (yes, I'm writing an axkit wiki in case anyone's interested) Anyway, that's off topic, because the point was you were trying to argue (IIRC) why would you bother hand generating XML from your data just to get access to XML tools. But XSP's two taglib modules (look at the docs on search.cpan.org, rather than on axkit.org) do that conversion automatically for you. - -- :-get a SMart net/:- -BEGIN PGP SIGNATURE- Version: GnuPG v1.0.7 (GNU/Linux) iD8DBQE9CErhVBc71ct6OywRAn67AJ9E9o+MAnvkbXutEycFk+y7LAEVQwCfeUuI 95rN/7rb51T9wLJgY3EamL0= =c8HN -END PGP SIGNATURE-
RE: separating C from V in MVC
-Original Message- From: Perrin Harkins [mailto:[EMAIL PROTECTED]] Sent: 13 June 2002 03:43 To: Fran Fabrizio; [EMAIL PROTECTED] Subject: Re: separating C from V in MVC 2. Does the first part of my code above even remotely resemble a Controller? Sort of. It does choose a view and it does parse some user input, but a controller is more than just a dispatcher. It would include some of the code that you're currently putting into your doDoctorActivity() sub. The idea is that the model objects represent just the data in your application (the nouns) and the controller understands how to translate user input into a series of method calls on the model objects to carry out the user's request. It's hard to give a good example that is short, but let's say you were building an application to sell concert tickets. The act of buying the ticket might involve model objects representing a concert, a user, a form of payment, etc. The concert object knows how to reserve a specific seat (or call a seat object to do that). The payment object knows how to verify and charge a credit card. The user object has a mailing address. The controller knows how to turn the user's form data into a bunch of method calls on these objects that accomplish reserving the ticket and charging the user. If you find yourself writing a BuyTicket module, that's a controller not a model object. I disagree with this definition of a Controller. A Controller is primarily responsible for mapping user input onto a business Model, and should not know that buying a ticket requires creation of concert, payment, seat, client, theatre, agent, reservation, whatever objects. In the same way that the View keeps the output format independent of the Model properties, the Controller keeps the User Input method independent of business logic. This is the reason for having a Controller class. Consider that your mod_perl website Controllers will have to understand all about web requests, headers, error headers, cookies, sessions, redirects, URLs and URL decoding etc etc - these are things that relate directly to how the user is interacting with the Model. In the concert example, the Controller would interpret the web request, create a Ticket object, and call $Ticket-buy( %all_the_cleaned_up_params ). It would then pass this to the View to render. That's it. Consider the case where you wanted to buy hundreds or even thousands of tickets in a batch process - maybe you have agents that collect all the details for Kylie concerts, and then send them to you in a file. If you had made the mistake of creating a web Controller aka BuyTicket() module that understood it had to create concert, payment, seat, client, theatre, agent, reservation, whatever objects, you would have to duplicate all this logic AGAIN in the batch process Controller. You now have to maintain the business logic in two places. Always keep the _business_ behaviour in Models. The $Ticket-buy() processing must instantiate and create relationships to all the other objects it needs. Put all things that are specific to handling the User Interaction (eg web request) into your Controller. Business logic always goes into a Model. The idea is that the model objects represent just the data in your application (the nouns) and the controller understands how to translate user input into a series of method calls on the model objects to carry out the user's request. Models are not just collections of stateful data, they are the right place to encapsulate complex business behaviour. At the risk of repetition, all behaviour [e.g. $Ticket-buy()] that is not specific to the User Interface should go into Models. Controller and View are closely related elements of GUI. This is like the old 'Two Tier App' problem... when business logic and GUI become inexorably entwined, maintenance goes out the window. Have a look at this picture: http://www.ddj.com/documents/s=867/ddj0105i/0105if2.htm which comes from this article: http://www.ddj.com/documents/s=867/ddj0105i/0105i.htm Maybe in the future, we will get drag-and-drop via the web - interpreting this should go into the Controller. Maybe in the future you will change the business requirements for buying Tickets - this will go in a Model, and the effect will be felt consistently in both your web applications and your batch processing. Regards Jeff
RE: separating C from V in MVC
Ok so Collections was the missing piece in my puzzle. Very interesting (and intuitive now that you present it to me). Controller: --- my $Stale = Model::WatchCollection-new( status = 'stale' ); Controller: --- my $WC= Model::WatchCollection-new(); Out of these two, I would think that the first one is actually better. What if you have 300,000 watches and only 25 are stale, for example (numbers that are not all that far from the truth, in my case)? That'd be a lot of data I'd be slinging around in the 2nd example. Which is probably what you meant by might be better. :-) Thanks for the example code, it was very enlightening! I'll digest further at the office this morning. -Fran
Re: separating C from V in MVC
I just wanted to comment on Number 3, here. Scroll down ;-) kyle dawkins wrote: Fran (et al) I've stayed out of the MVC chitchat for a long time (very interesting thread) because it's such a deep topic. But seeing as how Fran has some concrete questions... 3. How do you prevent a Controller from just becoming another big if statement, or is this their purpose in life? See Jeff's previous mail. Your structure is crying out for a dispatch table; Jeff suggests building this out of a hash that defines what actions to perform based on what your query values are. That's a great place to start. GET RID OF YOUR BIG IF STATEMENT ASAP. If I read this right, then it's something I am already doing and I'll throw it in here to show: ## My idea of a dispatch table! my %actions = ( 'view' = 'FES::Control::View', 'logout' = 'FES::Control::Logout', 'edit' = 'FES::Control::Edit', 'notes'= 'FES::Control::Notes', 'save' = 'FES::Control::Save', 'calendar' = 'FES::Util::Calendar', ); sub handler { my $r = Apache::Request-new(shift); ## BEGIN ignore (DECLINE) image requests and allow regular apache to handle them. return DECLINED if $r-content_type =~ /image/; ## END ignore image requests my $act = $r-param('act') || 'view'; if (my $h = $actions{$act}) { $r-push_handlers(PerlHandler = $h); $r-handler('perl-script'); return DECLINED; } else { my $stmt = There is no such action as \' . $act . \'\n; $r-pnotes('error', $stmt); $r-push_handlers(PerlHandler = 'FES::Error::Error'); $r-handler('perl-script'); return DONE; } ## end else [ if (my $h = $actions{$act... } 1; That's how I impliment at least _part_ of my controller without resorting to huge IF statements. Is this what was meant guys? --Jon R. If this is overly simplistic, or not what you meant, feel free to smack me around.
Re: separating C from V in MVC
Fran Out of these two, I would think that the first one is actually better. What if you have 300,000 watches and only 25 are stale, for example (numbers that are not all that far from the truth, in my case)? That'd be a lot of data I'd be slinging around in the 2nd example. Which is probably what you meant by might be better. :-) Jeff's example was very abbreviated to make a point. In your case, you should think about two things: 1) the representation of your data 2) the fetching of your data Since you could have a zillion watches, you could use something like my $staleWatches = WatchManager::watchesWithStatus(stale); This allows you to implement the watchesWithStatus method any way you choose, and simply returning an arrayref of matching watches. Then you can pass that arrayref to your View, which, as Jeff says, should apply some transform to your data to produce your report.I realise this is essentially what Jeff is saying but the key point is that you don't need to have all 300,000 watches in memory... you can abstract the data using a Manager (or Broker, or... ) so you hide the data store. Cheers Kyle Dawkins Central Park Software
RE: separating C from V in MVC
-Original Message- From: Fran Fabrizio [mailto:[EMAIL PROTECTED]] Sent: 13 June 2002 13:23 To: Jeff AA Cc: [EMAIL PROTECTED] Subject: RE: separating C from V in MVC Controller: --- my $Stale = Model::WatchCollection-new( status = 'stale' ); Controller: --- my $WC= Model::WatchCollection-new(); Out of these two, I would think that the first one is actually better. What if you have 300,000 watches and only 25 are stale, for example (numbers that are not all that far from the truth, in my Don't make the mistake of fetching all the data when a Collection is instantiated. It is usually better to make the Collection only really fetch data when a View actually asks for it by calling $WC-fetch( status = 'stale' ), after all, sometimes you might go down another route and the View might never call fetch() - for example if there is an exception and you decide not to bother showing stale Watches. Also, you should generally not fetch everything from the database unless there is a very good reason to do so. Try to keep your memory usage to a minimum, and restrict the result set to something useful. I recall a system that used to pop up a dialog saying 'Warning: This will return 645,345 rows' and the only user option was 'Ok'! I have seen about 4.2 million Collection designs, and my current favourite is an abstraction of the Borland Data Engine DB/Table/Dataset design (BDE) in conjunction with some of the Java collection concepts. Common Collection niceties include things like 'find me Watch ABC' in the Collection. A Collection can have the concept of a 'current' thing so that a View can display both the list of Watches in a table, and more detailed attributes of the 'currently selected' Watch object etc. If you are going to support paginated collections, you should build this into your base Collection class. So far we have been talking about flat Collections, don't forget that some of them are not flat, but hierarchical - e.g. tree-like, and some are circular e.g. no beginning and no end, etc. ciao Jeff
Re: separating C from V in MVC
Fran Fabrizio wrote: Now, how do you represent in the model a complex query that joins across 5 of the nouns? Others have already commented on this, but I want to point out that this is a general OO modelling question, not an MVC one, and there are many resources available to help you learn this stuff. I'd suggest getting to your local computer book store and browsing through some OO programming titles. In your concert example, if I wanted to define a report that showed me all of the seats that were purchased by people from New Jersey with a Mastercard in the last week, how would I represent that? That's a tricky one, because it doesn't make much sense to put all that logic about finding users' home states and payment types into a Concert class. You could manipulate the objects to accomplish this: my wanted_seats; my seats = Model::Concert-findSeatsReservedAfter($date); foreach my $seat (seats) { if ($seat-person()-address()-state() = 'NJ') { push wanted_seats, $seat; } } As you can see it gets messy fast, and I didn't even cover the Mastercard part. It would probably have terruble performance too. This is why people usually just write this kind of report as a big SQL query instead. You can make a model object called ConcertSeatSearch: seats = Model::ConcertSeatSearch-findSeats( reserved_after = $date, payment_type = $card, user_state = $state, ); Just be careful that you don't end up making this into something that mirrors the SQL exactly. There might be 4 tables involved in finding out what kind of credit card the user had, but that gets hidden behind this API. If you find yourself writing classes that take options like where = 'date ' . $date you are reinventing SQL, and you've lost your abstraction. - Perrin
Re: separating C from V in MVC
On 6/13/02 1:29 PM, Perrin Harkins wrote: Just be careful that you don't end up making this into something that mirrors the SQL exactly. There might be 4 tables involved in finding out what kind of credit card the user had, but that gets hidden behind this API. If you find yourself writing classes that take options like where = 'date ' . $date you are reinventing SQL, and you've lost your abstraction. Stringy stuff like that is certainly a poor abstraction (or no abstraction at all if it's stuck directly into the SQL!) But I've done stuff like this: Pets-get_pets(type = [ 'dog', 'cat' ], age = { and = { gt = 5, lt = 10 } }, name = { match = 'Fi.*' }); which is powerful enough to do most types of basic selects, but still abstract enough that the user of this class never actually types SQL fragments directly. Of course, the case above is a rarity. Usually, it'll be used in the simple form like: Pets-get_pets(type = 'dog', age = 5); But just having that more complex form in there for the one or two times you need it is sometimes valuable, IMO. And the overhead is minimal if you have a nice base class that supports all this stuff for you. -John
Re: separating C from V in MVC
On Thu, 13 Jun 2002, Perrin Harkins wrote: As you can see it gets messy fast, and I didn't even cover the Mastercard part. It would probably have terruble performance too. This is why people usually just write this kind of report as a big SQL query instead. You can make a model object called ConcertSeatSearch: seats = Model::ConcertSeatSearch-findSeats( reserved_after = $date, payment_type = $card, user_state = $state, ); Just be careful that you don't end up making this into something that mirrors the SQL exactly. There might be 4 tables involved in finding out what kind of credit card the user had, but that gets hidden behind this API. If you find yourself writing classes that take options like where = 'date ' . $date you are reinventing SQL, and you've lost your abstraction. This approach works for some things, but I think it falls down when it comes to doing complex database searches, particularly searches generated ad-hoc on multiple columns in multiple tables. This is why Alzabo is much lower-level than what you have above. I needed something where I could easily construct queries that might include 1+ tables, with various types of searches of individual columns in those tables (equal to, between, less than, like, etc.) with dynamic sorting (again, on any of the columns in any of the tables, ascending or descending). With what you're proposing, I think you could easily end up with either: A) a ridiculously flexible interface that looks sort of like SQL, except where it is SQL, except where it's only sort of like SQL, etc. B) a ridiculous profusion of classes, methods, or both. SQL has its place, and Alzabo merely provides a thin layer on top of it. Trying to jam a thick layer of OO-goodness over relational data is asking for a mess. OO has its place, but if your application is primarily about the database, I don't think that a heavy OO layer on top of that will do you much good. And OO has a huge impedance mismatch with relational data (irregardless of SQL or not). -dave /*== www.urth.org we await the New Sun ==*/
Re: separating C from V in MVC
Dave Rolsky writes: Trying to jam a thick layer of OO-goodness over relational data is asking for a mess. Most OLTP applications share a lot in common. The user inputs data in forms. The fields they edit often correspond one-to-one with database fields, and certainly their types. The user wants reports which are usually closely mapped to a table/view/join, i.e. an ordered list of tuples. A reasonable O/R mapping can solve this problem easily. Like Perl, it makes the easy things easy and the hard things possible. The bOP Pet Shop demostrates how you can build a simple application with only a couple of custom SQL queries. The rest are simple joins and CRUD. If you need more complex queries, there are escapes. You still probably end up with a list of tuples for your reports. The key we have found is avoiding indirection by naming fields and models the same in SQL and Perl objects. This allows you to seamlessly switch between the two. We've found the O/R mapping to be an indispensable part of the system. Since all data is contained in objects, the views/widgets don't need to how the data is populated. They access all data through a single interface. Rob
Re: separating C from V in MVC
On Thu, 13 Jun 2002, Rob Nagler wrote: Most OLTP applications share a lot in common. The user inputs data in forms. The fields they edit often correspond one-to-one with database fields, and certainly their types. The user wants reports which are usually closely mapped to a table/view/join, i.e. an ordered list of tuples. A reasonable O/R mapping can solve this problem easily. Like Perl, it makes the easy things easy and the hard things possible. The bOP Pet Shop demostrates how you can build a simple application with only a couple of custom SQL queries. The rest are simple joins and CRUD. If you need more complex queries, there are escapes. You still probably end up with a list of tuples for your reports. The key we have found is avoiding indirection by naming fields and models the same in SQL and Perl objects. This allows you to seamlessly switch between the two. The Pet Shop has a grand total of 13 tables. How well does this approach work with 90 tables? How does it handle arbitrary queries that may join 1-6 tables, with conditionals and sorting of arbitrary complexity? We've found the O/R mapping to be an indispensable part of the system. Since all data is contained in objects, the views/widgets don't need to how the data is populated. They access all data through a single interface. I'm not a big fan of O/R. I prefer R/O. But to each their own. -dave /*== www.urth.org we await the New Sun ==*/
Re: separating C from V in MVC
At 12:58 PM 6/14/2002, Dave Rolsky wrote: On Thu, 13 Jun 2002, Rob Nagler wrote: I'm not a big fan of O/R. I prefer R/O. But to each their own. Would one of you mind providing a 1 paragraph definition of each? I am afraid that I am starting to get lost in the semantic differences of controllers and actions and O/R, R/O?
Re: separating C from V in MVC
On Fri, 14 Jun 2002, Gunther Birznieks wrote: Would one of you mind providing a 1 paragraph definition of each? I am afraid that I am starting to get lost in the semantic differences of controllers and actions and O/R, R/O? Well, here's my take on it. An Object-Relational mapper takes objects and stores them in a relational database, as transparently as possible. I think the most pure example of this I've seen in the Perl world is Tangram (www.tangram-persistence.org). SPOPS is also an O-R mapper (actually, its a generic Object persistence mechanism but it seems to most feature-rich when used with an RDBMS). A Relational-Object takes a relational database, and provides access to it (select, insert, update, delete) via objects. Class::DBI, Alzabo, and DBIx::RecordSet are examples of such a beast. I think what it comes down to is how do you start thinking your project? If the first thing you think about is classes, objects, hierarchies, delegation, etc., then an O-R mapper may be for you. Most applications need some sort of persistent data storage, and if you think of your app solely as a collection of objects, then an O-R mapper is a natural fit. However, if you're like me, and given an app, the first thing you think about is _data_ and relationships, then a R-O mapper may be better. I for one start a project by designing a relational schema for the data. Then I want some nice programmatic way to get at it so Alzabo is key for me. Of course, all this assumes some large amount of persistent data, as is the case with many (but not all) web apps. OTOH, if you don't have much (or any) persistent data, this is all meaningless. For example, when I work on Mason I think objects. But when I work on my Hong Kong movie DB project, I think about tables. I have 90-some tables and I don't really want to create 90-some individual classes, plus some ungodly number of query classes (as proposed by Perrin) to deal with it. Thanks, but no thanks. OTOH, I hate writing raw SQL and I hate generating SQL dynamically even more. Alzabo provides a nice layer over SQL, provides a multitude of convenience methods, has hook/trigger support, supports caching, transactions, and facilitates writing additional canned query methods as needed, and much much more ;) -dave /*== www.urth.org we await the New Sun ==*/
Re: separating C from V in MVC
Shop demostrates how you can build a simple application with only a couple of custom SQL queries. The rest are simple joins and CRUD. If you need more complex queries, there are escapes. You still probably end up with a list of tuples for your reports. The key we have found is avoiding indirection by naming fields and models the same in SQL and Perl objects. This allows you to seamlessly switch between the two. How well does this approach work with 90 tables? How does it handle arbitrary queries that may join 1-6 tables, with conditionals and sorting of arbitrary complexity? I'd have to agree, most of the real-world scenarios I have run across do not consist of these neat 1-to-1 field to attribute type of mappings where the majority of the queries are simple inserts or selects from a single table or simple joins. Most of the apps I work on quickly evolve to the point of many (in my current case, 120+) tables and where most of the queries are gathering data for reports/views that bring data together from several tables. Joins of 5+ tables, unions, excepts, subselects, self-joins, complex sorting/grouping rules, etc are all commonplace and this is where I think overzealous attempts to abstract the queries away fall apart. I guess I'm more of the Perrin school of thought, where I prefer crafting all the SQL directly. I don't typically find apps that just mirror some subset of one of the db tables to be all that interesting. After all, it's the relationships between the data that make the data interesting, and by necessity this means your queries will be complex. And looking over the stuff outlined at poop.sourceforge.net, there's not too many models/frameworks out there that can accurately abstract ALL of SQL, and if it only does a subset, I feel like that's shooting myself in the foot. -Fran
Re: separating C from V in MVC
Dave Rolsky writes: The Pet Shop has a grand total of 13 tables. How well does this approach work with 90 tables? Works fine with bivio.com, which has 50 tables. How does it handle arbitrary queries that may join 1-6 tables, with conditionals and sorting of arbitrary complexity? The ListModel can override or augment its query. You can load a ListModel from an arbitrary data source as a result. After the load, it can fix up rows, e.g. computing percent portfolio is not done in SQL but in Perl in internal_post_load_row(). The automatic sorting is handy for simple joins. For complex queries, there's no fully automatic solution for sorting. Here's a simple query: http://petshop.bivio.biz/pub/products?p=DOGS The ListModel declares which columns are sortable: order_by = [ 'Product.name', 'Product.product_id', ], The view doesn't need to say anything, because the Table widget queries the ListModel meta-data. The SQL query is dynamically constructed by the o HTTP query value. For complex queries, you may be able to take advantage of the sort infrastructure. There are no guarantees, but you have the rope. The software is designed for the 80% solution. As we see patterns develop in our code, we add general cases to the infrastructure. I'm not a big fan of O/R. I prefer R/O. But to each their own. I guess we do R/O in the sense that we design the database relationally and then map PropertyModels one-to-one with the tables. Is that what you mean by R/O? Rob
Re: separating C from V in MVC
On Fri, 14 Jun 2002, Fran Fabrizio wrote: How well does this approach work with 90 tables? How does it handle arbitrary queries that may join 1-6 tables, with conditionals and sorting of arbitrary complexity? I'd have to agree, most of the real-world scenarios I have run across do not consist of these neat 1-to-1 field to attribute type of mappings where the majority of the queries are simple inserts or selects from a single table or simple joins. Most of the apps I work on quickly evolve to the point of many (in my current case, 120+) tables and where most of the queries are gathering data for reports/views that bring data together from several tables. Joins of 5+ tables, unions, excepts, subselects, self-joins, complex sorting/grouping rules, etc are all commonplace and this is where I think overzealous attempts to abstract the queries away fall apart. I guess I'm more of the Perrin school of thought, where I prefer crafting all the SQL directly. I never said I like to actually write SQL directly. See below ... I don't typically find apps that just mirror some subset of one of the db tables to be all that interesting. After all, it's the relationships between the data that make the data interesting, and by necessity this means your queries will be complex. And looking over the stuff outlined at poop.sourceforge.net, there's not too many models/frameworks out there that can accurately abstract ALL of SQL, and if it only does a subset, I feel like that's shooting myself in the foot. Well, I'm the author of both that doc _and_ Alzabo, which of the R-O tools described in that document supports the most of SQL except for DBIx::RecordSet, which is quite a bit lower-level, but basically can be used for _any_ SQL (I think). Alzabo supports enough for me and my 90-table database. So far I haven't needed unions, excepts, or difference, nor have I needed subselects (Alzabo actually has some support for subselects, though not the first three). I do need complex joins, self-joins, joins with aliases, complex sorting grouping (though it doesn't support HAVING yet), outer joins, and all conditionals. Alzabo does support all of this, and frankly I find it easier to do this, particularly when it needs to be done on the fly, then I could by just generating SQL in the app itself. I'm all for _some_ abstraction. The eternal question is how much? -dave /*== www.urth.org we await the New Sun ==*/
Re: separating C from V in MVC
On Wednesday 12 June 2002 4:09 am, Rob Nagler wrote: Matt Sergeant writes: There's quite a few things that are a lot harder to do with XML in plain perl (especially in SAX) than they are in XSLT. This assumes you need XML in the first place. No, it does not. The rest of my post spoke about XML as a data format and set of tools, not as a syntax. Please stop thinking about XML as syntax!! It's trivial to manipulate Perl data structures in Perl. It's also easy to manipulate XML in Perl. However, it's impossible(?) to manipulate Perl data structures in XSLT. You seem to speak as someone who has never tried by the sounds of things. This is one of the things AxKit's XSP taglibs are designed to provide for. Matt.
Re: separating C from V in MVC
Ok, thanks to you all and this great discussion I want to try to make our current project into an MVC-style app, so what now? This MVC discussion could not have come at a better time - our little app is all grown up now and needs a real architecture. I have read the MVC threads in depth now, and I have questions. WHERE WE ARE NOW -- We have a multiuser application that has about oh, I dunno, 100 different screens to the interface. They can be roughly divided into the following areas - status, admin, registration, reports, and graphs. Most of the actions involve either retrieving data from a database or processing a form and inserting into a database (in other words, it's a very typical web application). This application started as a CGI script. For performance reasons, we installed mod_perl and use Apache::Registry to run it now. It's pretty much still a dumb CGI script with a mod_perl wrapper, but I did develop a couple of modules to do user authentication with AuthCookie-based solutions and tied that into Apache::Session for state maintenance between requests. The CGI script has grown to accomodate these ~ 100 actions and is now basically a 4,000 line if statement. The script decides which request to do based on a target= parameter passed in (in other words, target=summary or target=doctoractivity, etc...). For sanity's sake, many months ago, we switched to HTML::Template (our view) to define our screens, which has worked well to date. On the back end we have PostgreSQL with a healthy sized schema of around 150 tables or so that has ~ 350 megs of data and on the order of 500,000 transactions a day (lots of data turnover, some tables get UPDATEd so frequently as to have 100% data turnover within 15 minutes). Anyways, back to the perl part Basic code structure: [snip] my $dbh = DBI-connect( $r-dir_config('RMSDBI_DSN') , $r-dir_config('RMSDBI_user') , $r-dir_config('RMSDBI_password') ); # giant if statement - closest thing I have to a controller, I suppose if ($target = 'summary') { my $tmpl = getTemplate('summary'); doSummary($dbh,$tmpl); print header . $tmpl-output(); } elsif ($target = 'doctoractivity') { my $tmpl = getTemplate('doctoractivity'); doDoctorActivity($dbh,$tmpl); print header . $tmpl-output(); } elsif ... [snip] # lots of subs basically one per target, closest thing I have to a model, I suppose sub doSummary { ($dbh, $tmpl) = shift; $sth = $dbh-prepare(SQL STATEMENT HARD-CODED HERE); # process result set into hashes and arrays of hashes such as summary that HTML::Template wants [snip] $tmpl-param(summary = summary); } sub doDoctorActivity { ($dbh, $tmpl) = shift; $sth = $dbh-prepare(SQL STATEMENT HARD-CODED HERE); # process result set into hashes and arrays of hashes such as summary that HTML::Template wants [snip] $tmpl-param(summary = summary); } etc This basic pattern repeated ad infinitum. It's grown way out of control, is a pain to work with, and just feels wrong, very wrong. :-) To be fair, it grew very fast and it was all we (by we I mean the two of us that were this entire dept. back then) could do to keep up with the feature requests, let alone worry about proper architecting of the software. We're paying for it now, of course. WHERE WE WANT TO BE -- I would like to introduce some semblance of organisation, sanity, maintainability, separation of logic, etc to this project. In other words, MVC would be a good fit. Some of the concrete, basic questions I have are: 1. Is there one Controller or many? Should I have one for each main area of my site? /myapp/admin/ goes to an Admin Controller, /myapp/reports to another controller, etc... 2. Does the first part of my code above even remotely resemble a Controller? I mean, it takes the input, calls essentially a 'model' object (but passing it the view object, nice, eh? =), but then seems to break the model nicely by doing things like printing out the HTML from the Controller, etc... 3. How do you prevent a Controller from just becoming another big if statement, or is this their purpose in life? 4. In the case of a form, what perl structure is used to pass the data into the model? 5. Do you create an actual class for each form? 6. Do you need to create objects at all? Is OO a prerequisite to MVC? 6.5. (thought of while proofreading :-) Is the statement there is one set of controllers for each defined view correct? In other words, if we someday want to output the reports section of the site as Excel spreadsheets in addition to HTML, would we define a new set of controllers or how would that work? Now onto the model, I think I have a little better grasp of the model compared to the controller, but I have questions... 7a. Is it insane to leave my SQL hard-coded in there? The queries don't change all that much, and it's nice to have the query in
RE: separating C from V in MVC
From: Fran Fabrizio [mailto:[EMAIL PROTECTED]] Sent: 12 June 2002 21:48 Nothing indepth, just a quick response, but it looks like your huge if statement can be replaced using a hash. Maybe something like: # just an eg, this data is static and can be required from # your startup.pl so that all child get a shared copy %global::dispatch = ( summary = { template = 'summary', actions = [ 'doSummary', 'doOther' ] }, doctor = { template = 'docact, actions = [ 'healthyself', ] }, ) # In your generic Controller / Handler if ( exists $global::dispatch{$template} ) { my $dispatch = $global::dispatch{$template}; my $tmpl = getTemplate( $despatch-{template} ); foreach my $function ( @{$dispatch-{actions} ) { $function($dbh,$tmpl); } print header . %tmpl-output(); } else { unavailable(); } The nice thing about this is you end up with a generic Controller, and can separate the config off somewhere else. The Controller will probably change much less than your config, so separation makes sense. I don't really see an issue with the Controller being responsible for returning the response, after all it fielded the request in the first place. I would try hard to keep ALL HTML in the View world - whether you create a View class or use a templating approach. 0.02c Regards Jeff
RE: separating C from V in MVC
On Jun 12 Jeff wrote: From: Fran Fabrizio [mailto:[EMAIL PROTECTED]] Sent: 12 June 2002 21:48 Nothing indepth, just a quick response ... I too am using mod_perl just for Apache::Registry, and would also like to look for alternatives. Answers the questions posed by Fran would also help me and I bet other lurkers (L). Even just Jim JampL aka Japh wannabe
Re: separating C from V in MVC
Fran (et al) I've stayed out of the MVC chitchat for a long time (very interesting thread) because it's such a deep topic. But seeing as how Fran has some concrete questions... 3. How do you prevent a Controller from just becoming another big if statement, or is this their purpose in life? See Jeff's previous mail. Your structure is crying out for a dispatch table; Jeff suggests building this out of a hash that defines what actions to perform based on what your query values are. That's a great place to start. GET RID OF YOUR BIG IF STATEMENT ASAP. 6. Do you need to create objects at all? Is OO a prerequisite to MVC? No, but it makes it a lot easier in most cases. Passing objects between the M, the C and the V is way easier than building crappy hashes by hand and calling a zillion param methods. 7a. Is it insane to leave my SQL hard-coded in there? The queries don't change all that much, and it's nice to have the query in the same place as the processing of the result set so you can kind of see the structure of the result set better. This helps our less-experienced developers. OK, strong words here. REMOVE YOUR SQL. Move it into a layer that deals with the DB and vends consistently formed data (objects if you can manage it).Your controller shouldn't know anything about your DB, so create a class that essentially is every entry and exit point to and from your DB, and have that keep the database handle as a class variable. What's easier for your newbie programmers... your code as it is now, or this: sub doDoctorActivity { my $tmpl = shift; my results = DataStore::objectsForDoctorActivity(); ViewManager::someMungingMethod($tmpl, \@results); return $tmpl; } Think of how clean your code is with no more $dbh references or ifs. Think how many fewer lines of code you will have to maintain. Fewer lines is good. Remember that. It is a HUGE gain to isolate your DB entry points and place them in one carefully controlled class. I am often amazed at how blind some developers can be about SQL. Most of the people on this list realise that mixing HTML and perl is bad, and most of us can see why. But I am constantly depressed that not nearly as many people appreciate that it is THE SAME FOR PERL AND SQL. SQL intermixed with Perl is just nasty and you need to move it into a limited space that you can easily control. Obviously, it's necessary; you need your perl to talk to your DB. But it should be very very carefully managed and moved somewhere where its impact on the source is minimal. Right now I have the evil task of optimising a zillion lines of bad perl code written by a company I used to work for. They have asked me to come back and save the project... and it's a frigging mess because of all the SQL. THere are so few places where you can cache query results, for example, because there are pages and pages of crap like $sql .= AND some_other_stupid_table.id = another_dumbass_table.stupid_table_id; if ($myAssIsBlue) { $sql .= AND some_table.my_ass IN ('BLUE','BLUISH','CYAN'); } ad nauseum. What a load of utter shite. 7d. Or do I -really- want an object/structure that represents every result set we need to get back from the database? If I were you I would create a parent class that represents a basic DB row and use that. When you need custom behaviour, subclass it and bless the rows into the subclass. Adding an Object Structure can be as simple as blessing your hashes that come back from the DB into a class, remember that. 8a. What structures are used to pass back the data from the model through the controller to the view? 8b. The view is expecting HTML::Template style hashes and arrays, do I form these in the model (which seems to be too much knowledge of the view while still in the model) or does the controller convert it to the structures expected by the HTML::Template view? 8c. The model is getting DBI record sets from the db. I have to put this data into -something-, why not the exact format that HTML::Template view needs rather than process it twice? Well, pretend you actually had objects coming back from your DB. Surely your controller should pass those objects to your view as is...? That's the whole point. Your view should be responsible for displaying them. I have seen a lot of talk about HTML::Template being a View layer. It's not. It's the bottom of the View layer. You need to write the top of the view layer yourself, that takes your data (objects, whatever) and vends it to HTML::Template in the right way. Kyle Dawkins Central Park Software
Re: separating C from V in MVC
Wow, this is a long one. As usual, everyone has slightly different ideas about how to do MVC, so keep a grain of salt handy. This basic pattern repeated ad infinitum. It's grown way out of control, is a pain to work with, and just feels wrong, very wrong. :-) We've all been there. 1. Is there one Controller or many? Usually there are many. Should I have one for each main area of my site? /myapp/admin/ goes to an Admin Controller, /myapp/reports to another controller, etc... That's how I would do it. The idea is to group the things that are related together, since they tend to change at the same time. 2. Does the first part of my code above even remotely resemble a Controller? Sort of. It does choose a view and it does parse some user input, but a controller is more than just a dispatcher. It would include some of the code that you're currently putting into your doDoctorActivity() sub. The idea is that the model objects represent just the data in your application (the nouns) and the controller understands how to translate user input into a series of method calls on the model objects to carry out the user's request. It's hard to give a good example that is short, but let's say you were building an application to sell concert tickets. The act of buying the ticket might involve model objects representing a concert, a user, a form of payment, etc. The concert object knows how to reserve a specific seat (or call a seat object to do that). The payment object knows how to verify and charge a credit card. The user object has a mailing address. The controller knows how to turn the user's form data into a bunch of method calls on these objects that accomplish reserving the ticket and charging the user. If you find yourself writing a BuyTicket module, that's a controller not a model object. 3. How do you prevent a Controller from just becoming another big if statement, or is this their purpose in life? If you break up your app into multiple controllers, there will probably only be a few different actions that each one handles. That's a pretty small if statement, or you could use a dispatch table. Modules like CGI::Application have already written the dispatch table code for you, so you just provide the configuration that maps actions to subroutines. 4. In the case of a form, what perl structure is used to pass the data into the model? You don't pass a form directly to a model object. You parse the form, then you use the API provided by the model object. Remember, we want to be able to use these same model objects from a cron job. my $hospital = $apr-param('hospital'); $doctor-set_hospital($hospital); 5. Do you create an actual class for each form? Similar to #1, each form might have it's own controller class, or you might group some related forms (that act on the same data) together in a single controller. 6. Do you need to create objects at all? Is OO a prerequisite to MVC? Modelling your data as objects is sort of an underlying assumption in MVC. You could do a clean design without using OO, but it would be a little odd and the model objects might not be very reusable. 6.5. (thought of while proofreading :-) Is the statement there is one set of controllers for each defined view correct? No. In other words, if we someday want to output the reports section of the site as Excel spreadsheets in addition to HTML, would we define a new set of controllers or how would that work? You would make your existing controllers understand the piece of user input or context that means they want Excel format, and have them pass the model data to a different view in that case. 7a. Is it insane to leave my SQL hard-coded in there? You're going to have SQL somewhere, but if you wrap it up into objects that represent your data, it's easier to maintain. It hides all of that specific database knowledge from the rest of the application and avoids repitition. At eToys we had a tremendous amount of data associated with each product. It spanned many tables and was not very easy to work with. However, once I had written an object representing a product, the search code, shopping cart code, product page code, etc. could all use it. When we added new properties, I only had to do it one place. OO modelling is a big subject and lots of good books have been written on it, so I won't say more about it here. 7b. Should I really investigate real object persistence like discussed at the POOP site (I have used Tangram with some success on tiny side projects but nothing remotely this size)? Only if you like what it does for you. I generally prefer to write the SQL myself because of the tuning opportunities it affords, but this is the sort of topic that many people have strong opinions on. Anyway, objects that contain hand-coded SQL are just as real as objects that use a POOP module to generate the SQL for them. Begging the question, should I really be migrating to
Re: separating C from V in MVC
-BEGIN PGP SIGNED MESSAGE- Hash: SHA1 On Monday 10 June 2002 11:23 pm, Vuillemot, Ward W wrote: : Really interesting, xml : appears to be : the final destination for most of us, even if now i : prefer objects. : : Ciao, Valerio That is my big question. Is XML/XSLT really the right solution? Using SAX along with having tags call handlers seems like a pretty powerful way to get a very cool tool to build powerful templating services. I haven't decided if XSLT really is worth the effort as it just seems like a glorified XML (yes; it is indeed) -- what I mean to say, does XSLT really have any real value since everything it does can be done in Perl. If I got make handlers for XSLT, too -- then why even use XSLT? Just go back to plain XML and do it all on my own, no? There's quite a few things that are a lot harder to do with XML in plain perl (especially in SAX) than they are in XSLT. It's really hard to explain this to anyone who hasn't yet learned XSLT's template model, but the simplest thing to describe is that looping back to previous tags is really hard with SAX (you have to use some sort of node caching technique). One thing a lot of people will argue is that XSLT is verbose and ugly. And I totally agree. But get over it. Perl is ugly too. But once you start using XSLT for any length of time you start to realise just why it is designed like it is, and you start to appreciate that design (and this is from someone who has so far designed *two* alternatives to XSLT!). - -- :-get a SMart net/:- -BEGIN PGP SIGNATURE- Version: GnuPG v1.0.7 (GNU/Linux) iD8DBQE9BZcbVBc71ct6OywRAv81AKDMDkWvAOhwY3A0vDlxxHSK7Y6qOACgm3ni VRLe9kmR9i3tDcMJAKr8d7s= =2Xpn -END PGP SIGNATURE-
RE: separating C from V in MVC
From: Rob Nagler [mailto:[EMAIL PROTECTED]] Sent: 10 June 2002 20:41 ... a Facade is the front face of the web site which includes colors, text, URLs, etc. All the other MVC components talk to the currently selected Facade when they need these values. The controller calls Bivio::UI::Task-parse_uri, which strips the *facade from the URL (if there) and sets the facade before parsing the rest of the URL. The default Facade is www.bivio.biz, which is why we don't need a rewrite. The links are generated by the Facade component Bivio::UI::Task. Sounds interesting, can you briefly describe the MVCF parts, and what their responsibilities are? Have you split the View into View + Facade? What are the differences between your MVCF and the MVP pattern? This allows the Facade to pick its own URLs. ... URLs are part of your user interface, not your controller. I think I like this, though the w3 might not 8-) We rarely change the controller except to add new function. Query and form values are parsed by the Models after they are translated to key/value format by the controller. I definitely like this - small number of relatively generic Controllers seems to me to be a desirable goal of an MVC arch. abstracted the concept of paging and drill down in our ListModel and Table classes. I find that the mix of business object e.g. Bank Account and presentation objects, e.g. Table can lead to confusion - are your Table objects just a way of organising data, or do they contain presentation style hints -e.g. dynamic width indication etc? Do you have something similar to a Bank Account object with some primary properties and containing a collection of current Transaction objects? Or do you focus on the presentation style objects - Tables, nested Tables, Lists etc? I looked over your site and code, compact and impressive - probably a stupid question, but are there any higher-level overviews of your approach / framework? TIA Jeff
Re: separating C from V in MVC
On Mon, 2002-06-10 at 13:29, Ray Zimmerman wrote: So how is everybody else handling URL mapping? Do others group this kind of data together with fonts, colors, etc? And where do you define it? As Perrin mentioned, OpenInteract does this by allowing individual packages (distributable applications) to define the handlers they support. A package does this by defining actions which at server startup get collected into a data structure called the action table. A single mod_perl handler catches all requests, looks up the URL in the action table and dispatches the request to the appropriate handler. That handler is free to pass on the request to other actions as well, since every part of the system is able to lookup actions based on a key. Entries in the action table can also be used as components -- displayable items that don't stand by themselves but contribute to a full page. Examples include boxes, common search forms, dependent object listings, etc. Currently, here's what an action looks like, as found in the 'base_user' package distibuted with OpenInteract: $action = { 'user'= { 'class'= 'OpenInteract::Handler::User', 'security' = 'no', }, 'newuser' = { 'class'= 'OpenInteract::Handler::NewUser', 'error'= [ 'OpenInteract::Error::User' ], 'security' = 'no', }, }; All information is available through a lookup to the action table. One of the modifications I'm working on now will allow you to add more information to the action and have it available in an object that is instantiated by the dispatcher which then tells the object to run itself. Chris -- Chris Winters ([EMAIL PROTECTED]) Building enterprise-capable snack solutions since 1988.
Re: separating C from V in MVC
On Tuesday, June 11, 2002, at 01:37 PM, Chris Winters wrote: On Mon, 2002-06-10 at 13:29, Ray Zimmerman wrote: So how is everybody else handling URL mapping? Do others group this kind of data together with fonts, colors, etc? And where do you define it? A single mod_perl handler catches all requests, looks up the URL in the action table and dispatches the request to the appropriate handler. That handler is free to pass on the request to other actions as well, since every part of the system is able to lookup actions based on a key. Currently OpenFrame does something similar. We have a slot which dispatches to an application based on the URL. However, I think for future versions applications will be 'slots', and they can just do something or nothing depending on the URL, which allows multiple applications to run on the same request, which fixes my 'how the heck do I make subrequests work' nightmare. We're also going to provide a 'forced' mvc style Application type in the next version[0] which will be a container that has a model, a view, and a controller. The data that each of the MVC elements provides will simply be passed from one to the other inside the container. As what may be a departure from the norm, in OpenFrame templates, or a templating system is *not* the view part of MVC. Templates simply decide where to place the data on the screen - the view class does all the formatting and prep work. Regards, James. [0] of course this is the next version that has been being written for the last 3 months and not gotten anywhere. Sooner or later I will get around to turning thought into code, and then all will be right and good in the world[1]. [1] or at least in my world
Re: separating C from V in MVC
I know we are straying WOT, but I would love to get a better feel for XML, XSLT and AxKit. There are a lot of different systems out there. . .and part of me wants to just do it my way (in large part to learn), but I also realize that I really want to get to the business of also being productive. Per the below, I would imagine some would say XML in and of itself is not worth considering as a contender for being the basis for our C of MVC. AxKit bills itself as an XML application. Would ppl suggest just using an XSLT parser. . .or is it worth looking at AxKit. If anyone is willing to share their experiences, knowledge, insight -- off the ML is okay, too -- I would _really_ appreciate it! Thanks, Ward -BEGIN PGP SIGNED MESSAGE- Hash: SHA1 On Monday 10 June 2002 11:23 pm, Vuillemot, Ward W wrote: : Really interesting, xml : appears to be : the final destination for most of us, even if now i : prefer objects. : : Ciao, Valerio That is my big question. Is XML/XSLT really the right solution? Using SAX along with having tags call handlers seems like a pretty powerful way to get a very cool tool to build powerful templating services. I haven't decided if XSLT really is worth the effort as it just seems like a glorified XML (yes; it is indeed) -- what I mean to say, does XSLT really have any real value since everything it does can be done in Perl. If I got make handlers for XSLT, too -- then why even use XSLT? Just go back to plain XML and do it all on my own, no? There's quite a few things that are a lot harder to do with XML in plain perl (especially in SAX) than they are in XSLT. It's really hard to explain this to anyone who hasn't yet learned XSLT's template model, but the simplest thing to describe is that looping back to previous tags is really hard with SAX (you have to use some sort of node caching technique). One thing a lot of people will argue is that XSLT is verbose and ugly. And I totally agree. But get over it. Perl is ugly too. But once you start using XSLT for any length of time you start to realise just why it is designed like it is, and you start to appreciate that design (and this is from someone who has so far designed *two* alternatives to XSLT!). - -- :-get a SMart net/:- -BEGIN PGP SIGNATURE- Version: GnuPG v1.0.7 (GNU/Linux) iD8DBQE9BZcbVBc71ct6OywRAv81AKDMDkWvAOhwY3A0vDlxxHSK7Y6qOACgm3ni VRLe9kmR9i3tDcMJAKr8d7s= =2Xpn -END PGP SIGNATURE- -- Ward W. Vuillemot [EMAIL PROTECTED]
Re: separating C from V in MVC
On Tue, 11 Jun 2002, Ward Vuillemot wrote: I know we are straying WOT, but I would love to get a better feel for XML, XSLT and AxKit. There are a lot of different systems out there. . .and part of me wants to just do it my way (in large part to learn), but I also realize that I really want to get to the business of also being productive. Per the below, I would imagine some would say XML in and of itself is not worth considering as a contender for being the basis for our C of MVC. AxKit bills itself as an XML application. Would ppl suggest just using an XSLT parser. . .or is it worth looking at AxKit. If anyone is willing to share their experiences, knowledge, insight -- off the ML is okay, too -- I would _really_ appreciate it! A while ago (couple of months I think) on the AxKit-Dahut IRC channel Eric Cholet was raving about how he had discovered how cool XML was. What really happened was that Eric discovered that XML isn't about the Syntax, which seems to be what everybody focuses on (especially perl people I find). The beauty of XML is in the tools. Things like SAX, which allow you to build a pipeline of specialised tools for munging data, are really why XML is so great. I really can't put it as well as Eric did at the time. I only hope by using his name out loud here I can prompt him to post something ;-) Basically I would just suggest that the set of tools for manipulating XML are better than most of the other tools you currently use for munging data about. Taken a step further, while perl is cool at munging text, most of us don't just deal with text - we deal with trees, records, etc. So by combining Perl and XML you get the best of both those worlds. The XML solutions I've seen tend to be the least hacked looking systems I've seen in my relatively few years of experience. I know that's not specifically about AxKit. What AxKit does offer is a mature stable system for bringing these tools together, plus it offers nice ways to deliver the same content in different formats. -- !-- Matt -- :-Get a smart net/:-
Re: separating C from V in MVC
Ward Vuillemot wrote: I know we are straying WOT, but I would love to get a better feel for XML, XSLT and AxKit. Barrie Slaymaker has written a couple of articles on perl.com that serve as a good intro to AxKit. - Perrin
Re: separating C from V in MVC
John Hurst wrote: Still, I don't think that replacing this: Location /search SetHandler perl-script PerlHandler Controller::Search /Location with this: [% Ctrl.Search() %] makes Controller::Search any less a controller. You're right. It just looks kind of odd to me, invoking a template for something that is not a display-related task. It looks like the way people typically do MVC in Mason or Embperl, with a first template that doesn't do anything but invoke a module to take over the processing. Obviously, the stand-alone dynamic pages are not MVC at all. They exist because there are often 'glue' pages that don't warrant the comlexity of MVC (those that don't need M and have very simple VC needs). I agree that there is often a need for some quick and dirty internal-use pages (admin or reporting usually) that don't require the extra baggage. - Perrin
Re: separating C from V in MVC
On 6/11/02 12:46 PM, Perrin Harkins wrote: John Hurst wrote: Still, I don't think that replacing this: Location /search SetHandler perl-script PerlHandler Controller::Search /Location with this: [% Ctrl.Search() %] makes Controller::Search any less a controller. You're right. It just looks kind of odd to me, invoking a template for something that is not a display-related task. It looks like the way people typically do MVC in Mason or Embperl, with a first template that doesn't do anything but invoke a module to take over the processing. ...but it has several advantages. I particularly appreciate being able to add to or change parameters or behaviors before passing things off to the controller, for example. I can have several variants of the same controller living at different URLs, all pointing back to a single controller object. Don't think of it as invoking a template. Just think off it as an inverted dispatch mechanism: the actions camp out at their locations, as opposed to having their locations (in the httpd.conf) pointing at the controller modules. Or something... :) -John
Re: separating C from V in MVC
On Tue, 11 Jun 2002, John Siracusa wrote: You're right. It just looks kind of odd to me, invoking a template for something that is not a display-related task. It looks like the way people typically do MVC in Mason or Embperl, with a first template that doesn't do anything but invoke a module to take over the processing. ...but it has several advantages. I particularly appreciate being able to add to or change parameters or behaviors before passing things off to the controller, for example. I can have several variants of the same controller living at different URLs, all pointing back to a single controller object. I think that it is also more manageable by people who doesn't want to understand configurations; designers who worked with me found this approach handy. Don't think of it as invoking a template. Just think off it as an inverted dispatch mechanism: the actions camp out at their locations, as opposed to having their locations (in the httpd.conf) pointing at the controller modules. Or something... :) And it is a sort of grid layout, mentioned by someone in a previous message; but it still remains an impure approach :( Ciao, Valerio Valerio Paolini, http://130.136.3.200/~paolini -- what is open-source about? Learn, and then give back
Re: separating C from V in MVC
At 01:01 PM 06/11/02 -0400, John Siracusa wrote: On 6/11/02 12:46 PM, Perrin Harkins wrote: John Hurst wrote: Still, I don't think that replacing this: Location /search SetHandler perl-script PerlHandler Controller::Search /Location with this: [% Ctrl.Search() %] makes Controller::Search any less a controller. You're right. It just looks kind of odd to me, invoking a template for something that is not a display-related task. It looks like the way people typically do MVC in Mason or Embperl, with a first template that doesn't do anything but invoke a module to take over the processing. ...but it has several advantages. I particularly appreciate being able to add to or change parameters or behaviors before passing things off to the controller, for example. I can have several variants of the same controller living at different URLs, all pointing back to a single controller object. This is how CGI::Application works, but instead of calling a template page, it calls a script. The script is tiny -- defines a run mode, and perhaps parameters -- then calls the main script that does the heavy lifting, which in turn instantiates standard modules that provide standard functionality. I was intrigued by it, because at the time I was using a different approach with shopping software: each link or form action called the same script, which would figure out what needed to be done. Kind of like the tail wags the dog instead of the other way around. This is outside of MVC, but is nonetheless intriguing. I'm wondering if, in another 2-3 years, after the authors of the several Perl application frameworks have had more time to refine their designs, there will be convergence of issues like this. Am I wrong, or is this field of web applications a developing field for which there is no textbook principles of how to do it? Perl has enabled several people to take different approaches to it, whereas Microsoft's ASP is just one approach, PHP is just one approach, and I don't know if Java has multiple approaches or what. Will the various Perl approaches converge toward a common set of principles, and/or reveal as yet undiscerned patterns and architectures? Or maybe I'm imagining too much here... Ron Don't think of it as invoking a template. Just think off it as an inverted dispatch mechanism: the actions camp out at their locations, as opposed to having their locations (in the httpd.conf) pointing at the controller modules. Or something... :) -John
Re: separating C from V in MVC
[% Ctrl.Search() %] makes Controller::Search any less a controller. You're right. It just looks kind of odd to me, invoking a template for something that is not a display-related task. It looks like the way people typically do MVC in Mason or Embperl, with a first template that doesn't do anything but invoke a module to take over the processing. Embperl 2.0 can invoke such a controller (it's called application object there) after it has setup it's request parameters (GET/POST data, session data, etc.) and before any templates are get a chance to run. So this application object is able to do the necessary processing and give back parameters to Embperl so the right templates will be displayed, according to the result of the controllers processing. This approach has the benefit that Embperl does the tasks that need to be done for every request, so you don't have to care about it and can concentrate on the real controller functions. Additionaly it implements an object orientated approach, so you can get addtional benefits by spliting up your controllers functionality in different application objects, which inherit from each other. (same inherence schema can be used for templates) Gerald - Gerald Richterecos electronic communication services gmbh Internetconnect * Webserver/-design/-datenbanken * Consulting Post: Tulpenstrasse 5 D-55276 Dienheim b. Mainz E-Mail: [EMAIL PROTECTED] Voice:+49 6133 925131 WWW:http://www.ecos.de Fax: +49 6133 925152 -
Re: separating C from V in MVC
Gerald Richter wrote: Embperl 2.0 can invoke such a controller (it's called application object there) after it has setup it's request parameters (GET/POST data, session data, etc.) and before any templates are get a chance to run. That sounds like a good addition to Embperl. Can you give a URL for the documentation on how to use this? - Perrin
Re: separating C from V in MVC
Matt Sergeant writes: There's quite a few things that are a lot harder to do with XML in plain perl (especially in SAX) than they are in XSLT. This assumes you need XML in the first place. It's trivial to manipulate Perl data structures in Perl. It's also easy to manipulate XML in Perl. However, it's impossible(?) to manipulate Perl data structures in XSLT. Rob
Re: separating C from V in MVC
Gerald Richter wrote: Embperl 2.0 can invoke such a controller (it's called application object there) after it has setup it's request parameters (GET/POST data, session data, etc.) and before any templates are get a chance to run. That sounds like a good addition to Embperl. Can you give a URL for the documentation on how to use this? http://search.cpan.org/doc/GRICHTER/Embperl-2.0b7/Embperl/Object.pm contains a short paragraph about it (search for EMBPERL_OBJECT_APP ) and inside the Embperl distribution is an example application (see eg/web). I am currently working on improveing the docs for Embperl 2.0, since a lot of nice new features are rarly documented right now Gerald - Gerald Richterecos electronic communication services gmbh Internetconnect * Webserver/-design/-datenbanken * Consulting Post: Tulpenstrasse 5 D-55276 Dienheim b. Mainz E-Mail: [EMAIL PROTECTED] Voice:+49 6133 925131 WWW:http://www.ecos.de Fax: +49 6133 925152 -
Re: separating C from V in MVC
At 12:02 AM -0600 6/6/02, Rob Nagler wrote: To solve this problem, we added a letter. bOP is MVCF, where F stands for Facade. A Facade allows you to control icons, files, colors, fonts, text, and tasks. You can add other components, but we usually use text as a catch all, e.g. numeric formats. Facades can inherit from other facades and can be cloned from other facades. We use this to support different skins and co-brands. snip A Facade is the first thing set in a request. You then know what tasks are available and what URLs map to them. Take a look at: http://petshop.bivio.biz/src?s=Bivio::PetShop::Facade::PetShop All the URLs for the site are contained in this file. Anybody rendering a URL, does it through Bivio::UI::Task. Two specifically for Rob ... (1) What are you using to display the nice syntax-colored Perl source at http://petshop.bivio.biz/ ? (2) Are you using the term Facade in the same sense as in Design Patterns p. 185? If not, could you define what a facade is in terms of its role? I'm planning an MVC-type architecture for my web-app and am looking for a place to put the kinds of data you have in your Facade - URL mappings, colors, fonts, etc. It seems that some of it is data that is used strictly by the View (colors, fonts) and other parts (URL mapping) are used by the View (for generating links) and Controller (for calling the View or doing a redirect). ... and one for everybody ... So how is everybody else handling URL mapping? Do others group this kind of data together with fonts, colors, etc? And where do you define it? Very much appreciating all the MVC discussion ... -- Ray Zimmerman / e-mail: [EMAIL PROTECTED] / 428-B Phillips Hall Sr Research / phone: (607) 255-9645 / Cornell University Associate / FAX: (815) 377-3932 / Ithaca, NY 14853
Re: separating C from V in MVC
Ray Zimmerman wrote: So how is everybody else handling URL mapping? In httpd.conf: Location /search SetHandler perl-script PerlHandler Controller::Search /Location Location /cart SetHandler perl-script PerlHandler Controller::ShoppingCart /Location Most applications only have a handful of controllers, so this works fine. You could also look at the way OpenInteract does it, which allows you to gather all the related stuff including this configuration into a single package that you can install in one shot. - Perrin
Re: separating C from V in MVC
Ray Zimmerman wrote: So how is everybody else handling URL mapping? In the filesystem. Directly requested .tt files are all sent to a default template handler: Location /tt_engine SetHandler perl-script PerlHandler UAL::TTEngine /Location AddType text/tt .tt Action text/tt /tt_engine The default template handler provides a list of controllers via the Stash, allowing the layout people to place a link to a controller anywhere. Controllers may be re-used with modified behavior: % cat admin/proj-edit.tt [% Ctrl.DBEdit.run(ObjectType = 'Project') %] % cat admin/task-edit.tt [% Ctrl.DBEdit.run(ObjectType = 'Task') %] % cat admin/usermanager.tt [% Ctrl.UserManager.run() %] % cat admin/mailclient.tt [% Ctrl.MailClient.run() %] % cat user/mailclient.tt [% Ctrl.MailClient.run(AllowPOP3 = 0, AllowIMAP = 0, AllowMIME = 0) %] -jh
Re: separating C from V in MVC
Ray Zimmerman wrote: So how is everybody else handling URL mapping? On Mon, 10 Jun 2002, John Hurst wrote: In the filesystem. Directly requested .tt files are all sent to a default template handler: [...] % cat admin/proj-edit.tt [% Ctrl.DBEdit.run(ObjectType = 'Project') %] I used html pages with augmented tags parsed by a standard handler: img src=some.gif function=Class::method arg=foo kbit this way i can instantiate classes, named components, and call their methods. Programmers write classes wich in turn call templates. Designer can control 1) graphic layout by moving 'images' (and other tags of course) 2) view details modifying templates. There are other high level tools: img get=variable kbit img set=variable value=... kbit img placeholder=name kbit img include=URI filter=... kbit functions can use variables and fill placeholders. Every component can interact with the handler, receiving context infos (possibly including session data) and answering with some content plus HTTP codes, which seem to me quite explanatory. If someone wants to know more, please ask. This framework works in few dinamic sites here in Italy and is very handy to use, especially during periodic reorganization of the site (structure, design). Thank you for the excellent OT! Ciao, Valerio Valerio Paolini, http://130.136.3.200/~paolini -- what is open-source about? Learn, and then give back
Re: separating C from V in MVC
Valerio_Valdez Paolini wrote: On Mon, 10 Jun 2002, John Hurst wrote: In the filesystem. Directly requested .tt files are all sent to a default template handler: ... I used html pages with augmented tags parsed by a standard handler: Those are both interesting and may be the most appropriate solution for the problems you're working on, but I wouldn't call either of them MVC. You are going straight to a view (template) and letting it drive all the decisions. In an MVC application, you would go to a controller that would do some work and then decide which view to show. - Perrin
Re: separating C from V in MVC
Valerio_Valdez Paolini [EMAIL PROTECTED] wrote: Ray Zimmerman wrote: So how is everybody else handling URL mapping? On Mon, 10 Jun 2002, John Hurst wrote: In the filesystem. Directly requested .tt files are all sent to a default template handler: [...] % cat admin/proj-edit.tt [% Ctrl.DBEdit.run(ObjectType = 'Project') %] I used html pages with augmented tags parsed by a standard handler: I'm doing something similar, but using a database (and caches) for url-filename mappings (usually to Mason components, searching the component root path) and then using a filter in the autohandler to change urls of the form comp:docs/index to a url that maps to that component. This lets me rearrange the public view of the site without moving any files and allows me to rearrange the files without changing the public view. I'm working on a framework that will use the Mason component as the controller, Perl modules as the model, and either Mason components or TT templates called from the controller as the view. The view would output XML that would then be put through AxKit or similar by the autohandler to add style information and produce HTML or whatever format we needed. The end result is that the work-code (model) is indepenent of interface, the controller is independent of view, and the view is somewhat (via XML) independent of lookfeel. I don't have benchmarks yet to demonstrate its non-scalability. -- James Smith [EMAIL PROTECTED], 979-862-3725 Texas AM CIS Operating Systems Group, Unix
Re: separating C from V in MVC
On Mon, 10 Jun 2002, Perrin Harkins wrote: Those are both interesting and may be the most appropriate solution for the problems you're working on, but I wouldn't call either of them MVC. You are going straight to a view (template) and letting it drive all the decisions. In an MVC application, you would go to a controller that would do some work and then decide which view to show. You are right, I know this problem, but think at components as second level controllers, where i can work with Model and View. The ugly thing is having html, which belongs to View, in two places with Controller in the middle. The main focus here is to be friendly with ui people, shifting reusability towards them. Thank you for your comment! Ciao, Valerio Valerio Paolini, http://130.136.3.200/~paolini -- what is open-source about? Learn, and then give back
Re: separating C from V in MVC
On Mon, 10 Jun 2002, James G Smith wrote: I'm working on a framework that will use the Mason component as the controller, Perl modules as the model, and either Mason components or TT templates called from the controller as the view. The view would output XML that would then be put through AxKit or similar by the autohandler to add style information and produce HTML or whatever format we needed. It seems perfect for mod_perl2. Really interesting, xml appears to be the final destination for most of us, even if now i prefer objects. Ciao, Valerio Valerio Paolini, http://130.136.3.200/~paolini -- what is open-source about? Learn, and then give back
Re: separating C from V in MVC
-BEGIN PGP SIGNED MESSAGE- Hash: SHA1 On Monday 10 June 2002 11:09 pm, Valerio_Valdez Paolini wrote: On Mon, 10 Jun 2002, James G Smith wrote: I'm working on a framework that will use the Mason component as the controller, Perl modules as the model, and either Mason components or TT templates called from the controller as the view. The view would output XML that would then be put through AxKit or similar by the autohandler to add style information and produce HTML or whatever format we needed. It seems perfect for mod_perl2. Really interesting, xml appears to be the final destination for most of us, even if now i prefer objects. There's no conflict between using XML and using Objects if you're using AxKit. Especially thanks to Simon Cozen's nice new taglib. - -- :-get a SMart net/:- -BEGIN PGP SIGNATURE- Version: GnuPG v1.0.7 (GNU/Linux) iD8DBQE9BSVWVBc71ct6OywRAtMWAJ94l9mq+ZMWduAMHRD81mHV+a0V7gCgg/bP jPXqIBNKQD64RDnDRLatSBM= =wH5R -END PGP SIGNATURE-
RE: separating C from V in MVC
: Really interesting, xml : appears to be : the final destination for most of us, even if now i : prefer objects. : : Ciao, Valerio That is my big question. Is XML/XSLT really the right solution? Using SAX along with having tags call handlers seems like a pretty powerful way to get a very cool tool to build powerful templating services. I haven't decided if XSLT really is worth the effort as it just seems like a glorified XML (yes; it is indeed) -- what I mean to say, does XSLT really have any real value since everything it does can be done in Perl. If I got make handlers for XSLT, too -- then why even use XSLT? Just go back to plain XML and do it all on my own, no? Part of me wants to go XML as it seems like nearly embraced technology. And having the parsing, et cetera handled by something other my own Perl seems like a good way to remove some headaches and let me get to the job of coding useful things. ;)
Re: separating C from V in MVC
On Mon, 10 Jun 2002, Matt Sergeant wrote: It seems perfect for mod_perl2. Really interesting, xml appears to be the final destination for most of us, even if now i prefer objects. There's no conflict between using XML and using Objects if you're using AxKit. Especially thanks to Simon Cozen's nice new taglib. I know also this; i subscribed Axkit ml on 31 May 2000, but still does not have the courage to look at xml and co. :) I'll post a question on the other ml, ok? Ciao, Valerio Valerio Paolini, http://130.136.3.200/~paolini -- what is open-source about? Learn, and then give back
Re: separating C from V in MVC
Perrin Harkins wrote: On Mon, 10 Jun 2002, I wrote: In the filesystem. Directly requested .tt files are all sent to a default template handler: Those are both interesting and may be the most appropriate solution for the problems you're working on, but I wouldn't call either of them MVC. You are going straight to a view (template) and letting it drive all the decisions. In an MVC application, you would go to a controller that would do some work and then decide which view to show. I have three kinds of templates: controller entry stubs - called directly to invoke a controller view pages - called by controllers to display results stand-alone dynamic pages - called directly, may not invoke controller I would agree with you if my entry stubs did more than call up the controller, but those templates are simple one-liners that do nothing else. Once the controller has been called it takes over, processing request data, calling models, selecting views, etc. The only influence a stub template has on the view is that of defining the URL that the controller inherits (plus optional parameters as shown in my earlier message). Yes, a developer could make a mess of things by trying to put more stuff into a controller entry stub. We all seem to agree that any scheme can be polluted by poor discipline, and the arrangement I have described is as prone to abuse as any other. Still, I don't think that replacing this: Location /search SetHandler perl-script PerlHandler Controller::Search /Location with this: [% Ctrl.Search() %] makes Controller::Search any less a controller. I could enforce the separation of controller entry stubs from stand-alone templates and view templates by using additional file extensions and handlers, but no one has abused the system as it is so I'm erring on the side of my own laziness. Using the entry stub templates is handy because I don't need to mangle the server configuration to make controllers available from other locations (which means I can stay at the pub while others toil away). Obviously, the stand-alone dynamic pages are not MVC at all. They exist because there are often 'glue' pages that don't warrant the comlexity of MVC (those that don't need M and have very simple VC needs). It is much more convenient to code such pages in the same environment as the MVC stuff (that is, using the same globally defined variables, macros, etc.). -jh
Re: [Templates] Re: Separating Aspects (Re: separating C from V in MVC)
On Sat, Jun 08, 2002 at 08:51:48AM +0800, Gunther Birznieks wrote: I'm a huge fan of passing Date::Simple objects, which can then take a strftime format string: [% date.format(%d %b %y) %] [% date.format(%Y-%m-%d) %] And the latter does not require a programmer? Of course not. It just requires someone who can read a simple chart of strftime formats. I've never worked with a designer who hasn't been able to understand the DESCRIPTION section of, for example, http://unixhelp.ed.ac.uk/CGI/man-cgi?strftime+3 It wouldn't be difficult to make up a more designer friendly version of it if it was really needed. Tony
Re: separating C from V in MVC
On Thu, 6 Jun 2002 20:15:24 -0600, Rob Nagler [EMAIL PROTECTED] said: (http://sourceforge.net/projects/poop/). RN Great, another mailing list. :-) Thanks. It is not just mailing list. Don't miss http://poop.sourceforge.net/. It has nice review of most Perl OO persistence modules. -- Ilya Martynov (http://martynov.org/)
Re: separating C from V in MVC
On Fri, 2002-06-07 at 03:15, Rob Nagler wrote: Agreed. Perl is good at text manipulation. It is imiho superior to XSLT in all spaces which XSLT claims to solve. Once you have an XML parse tree in Perl, it's trivial to write a translator to any format more correctly than XSLT. My favorite example is XML to CSV. Every example I've seen in XSLT is cumbersome and wrong. You'd think it wouldn't be hard, but try it. ;-) XSLT is an XML to XML transformation tool. Seems fairly obvious to me it's not going to do XML to CSV very well. For that you use SAX. I disagree with you in all uses of transforming an XML tree into another XML tree. Right tool for the job, as always. Matt.
Re: separating C from V in MVC
On Thu, Jun 06, 2002 at 08:15:24PM -0600, Rob Nagler wrote: The issue here is not whether TT is a bad approach, but rather why the syntax is not Perl. One reason is that I like to have minimal syntax in the templates. One argument often used is that non-programmer find it easier to say foo.bar than $foo-{ bar }. But I think the more compelling argument is that even experienced programmers find it easier to write. It's just less syntax. I don't mind syntax in my Perl programs, it serves an important purpose there. But in my templates, I prefer to have everything as simple as possible. Another reason is that foo.bar deliberately abstracts the difference between $foo-{ bar } and $foo-bar(). You can change the underlying implementation of a data structure and you don't need to update your templates. A third reason is that by abandoning strict Perl syntax I can be much more flexible in providing a domain specific language tailored to the task of generating and manipulating content. A
Re: separating C from V in MVC
::really hesitates to step into this ... but like a train wreck ... he simply can't resist:: It's like asking why XML has different syntax and semantics from Perl. Well, if you read the XSLT spec and then look at an XSLT program, you'll see a lot of verbosity and a lot of general purpose constructs like variables, conditionals, and loops. I haven't done much with XSLT, but I do know you can get it in an infinite loop. That seems pretty general purpose to me. Well aside from the fact that XSLT is Turing complete (And thus theoretically as powerful as Perl or C or Java) the syntax structure of XSLT (because it is a derivitive of XML) makes it difficult to do some things (try writing a version of sed in XSLT). This I think was the original point. Perl handels Regex's better than C, this is one of the reasons people use Perl. It makes (some) hard things easy and (some) impossible things hard ... within it's domain. XSLT is no different. Use the appropriate tool (or Toolkit) for the problem. I think the rule is: if you can solve Towers of Hanoi in the language, its general purpose enough. True formatting languages, such as, Scribe do not contain general-purpose constructs, so you couldn't solve the Towers of Hanoi. HTML is another good example (ignoring script). I do want to point out for clarity and posterity that HTML and XSLT are siblings ... in that they are both applications of XML (or SGML). HTML is not Turing Complete while XSLT. Turing completeness has a mathmatic existance beyond the Towers of Hanoi problem. But I haven't seen it solved in TeX either (::know's there's gotta be a link for this::). Rob, is what you are suggesting that one should not use a turing complete language for visual markup or that simply the language should be the best match for the solution? I'm just looking for clarity on your position. Why is there so little discussion of the M in MVC? It's far from a trivial problem. As I am currently mostly writing M and C and would be interested in some thoughts on the issues surrounding M. Like what issues have other people come across and how have other's dealt with them? This is the biggest benefit I have gained thus far from Perrin's eToys article (that and using it to sell mod_perl to my superiors as a better solution than Java eToys delt with 10x these many customers ... I think our system can handle the load). -Chris -- [A] Genuinely skillful use of obscenities is uniformly absent on the Internet. -Karl Kleinpaste
Re: [Templates] Re: Separating Aspects (Re: separating C from V in MVC)
On Thu, Jun 06, 2002 at 05:08:56PM -0400, Sam Tregar wrote: Suppose you have a model object for a concert which includes a date. On one page, the designers want to dipslay the date in a verbose way with the month spelled out, but on another they want it abbreviated and fixed length so that dates line up nicely. Would you put that formatting in the controller? In the script: $template-param(long_date = $long_date, short_date = $short_date); In the template: The long date: tmpl_var long_date br The short date: tmpl_var short_date Can I vote for yick on this? A designer should never have to come to a programmer just to change the formatting of a date. I'm a huge fan of passing Date::Simple objects, which can then take a strftime format string: [% date.format(%d %b %y) %] [% date.format(%Y-%m-%d) %] Tony
Re: separating C from V in MVC
::realizes this may be going a bit futher a field ... but tries to maintain topicality:: Chris writes: Perl handels Regex's better than C, this is one of the reasons people use Perl. I disagree. Perl's Regex processor is written in C. The difference is that it has outgrown Henry Spencer's regexp library. Mmm semantic differences I yield the floor seneator, but I wish it to go on the record that Regex's are built into the main syntax of the Perl language, and are fully supported by the culture. While you must specifically link to and consiously add in Regex's in C. You can build a Hash, Queue and Stack in C as well, but that doesn't mean that they aren't generally simpler to use in Perl because they're built right into the language. It makes (some) hard things easy and (some) impossible things hard ... within it's domain. XSLT is no different. Use the appropriate tool (or Toolkit) for the problem. Agreed. Perl is good at text manipulation. It is imiho superior to XSLT in all spaces which XSLT claims to solve. Once you have an XML parse tree in Perl, it's trivial to write a translator to any format more correctly than XSLT. My favorite example is XML to CSV. Every example I've seen in XSLT is cumbersome and wrong. You'd think it wouldn't be hard, but try it. ;-) Well XSLT wasn't really designed (and shouldn't have been) to output plain text. Despite what the W3C says. It's designed to tranlsate between XML Vocabularies. I'll explain in a bit why I feel that XSLT is better suited for this than Perl. existance beyond the Towers of Hanoi problem. But I haven't seen it solved in TeX either (::know's there's gotta be a link for this::). I'm sure Randall wrote a TeX to TT translator to generate his TT version of ToH. ;-) Merlyn any comments here? Other Powers-That-Be? I could see this as a JAPH ... only for size N problems it would take N^2 years to print. Rob, is what you are suggesting that one should not use a turing complete language for visual markup or that simply the language should be the best match for the solution? I'm just looking for clarity on your position. The question really surrounds little languages. Perl is ideally suited to creating them. There's no reason to invent a new syntax ([% %]) or semantics for standard structures. I think you should write classes in Perl that map to some interface which defines the language. This is where I think we have a disagreement. In usability circles there is an idea that different things should be ... well ... different. If one button turns on the radio ... it shouldn't look anything like the button that launches the missles. This is why I find XSLT well suited for XML-XML transformations because it is visually/ideologically well suited to it's primary domain. If I'm dealing with the angle brackets and the tree structure ... then I'm thinking about the angle brackets and the tree structure ... eventually I'm zenning in the whole Angle Brackety Tree Structury-ness of the world. (I have a degree in english I know exactly how awful that sentance was.) It may be true that Perl can do it quicker and faster ... but for me the advantage to visually distinguishing the logically different parts helps future maintainability. C and Perl are distinctly different because the domains they are best suited (and designed) for are distinctly different. Nobody wishes Perl's syntax were more like that of C, Java, or Cobol. If they do they should probably be writing C, Java or Cobol. (Inline::Cobol anyone?) In MVC if each letter were written in it's own language it would be very easy to maintain the seperation. If it's generally impractical to use three distinct languages* one should keep as much visual distinction between the three as possible. *Generally people already do use three langauges though with the Template Language (HTML|ASP|TT|XSLT), the Controller Language (Perl) and the Model Language (SQL). It's pretty much gotten to the point where nobody gets fired for choosing Java. I've lost many contract bids because I didn't say Java was the right solution. I haven't lost a single customer who let us solve the problem for them. People don't approach a contractor and tell them what tools to build a house with. Why do they insist on doing it with programmers? -Chris -- [A] Genuinely skillful use of obscenities is uniformly absent on the Internet. -Karl Kleinpaste
Re: [Templates] Re: Separating Aspects (Re: separating C from V in MVC)
On Fri, Jun 07, 2002 at 09:14:25AM +0100, Tony Bowden wrote: On Thu, Jun 06, 2002 at 05:08:56PM -0400, Sam Tregar wrote: Suppose you have a model object for a concert which includes a date. On one page, the designers want to dipslay the date in a verbose way with the month spelled out, but on another they want it abbreviated and fixed length so that dates line up nicely. Would you put that formatting in the controller? In the script: $template-param(long_date = $long_date, short_date = $short_date); In the template: The long date: tmpl_var long_date br The short date: tmpl_var short_date Can I vote for yick on this? A designer should never have to come to a programmer just to change the formatting of a date. I'm a huge fan of passing Date::Simple objects, which can then take a strftime format string: [% date.format(%d %b %y) %] [% date.format(%Y-%m-%d) %] Tony xmlns:date=http://exslt.org/dates-and-times; wins for me. date:date-time() date:date() date:time() date:month-name() ... etc xslt solutions win for me because it its supported (or seems to be) by many major languages, and applications. xslt stylesheets can be processed, reused and shared with my c,perl, java,javascript, ruby, mozilla, ieexplorer ... kde apps, gnome apps ... etc Imagine having your templates and data supported and interoperable ... Aren't we trying to rid the world of proprietary (only works here) things? Ed (an axkit lover)
Re: separating C from V in MVC
On Thu, Jun 06, 2002 at 12:02:47AM -0600, Rob Nagler wrote: These are the reserve words of TT: [...] Looks an awful lot like the same keywords in any general-purpose programming language. Yep, I agree. You can use it like a programming language and it gives you more than enough rope to hang yourself, or at least get tangled around your feet and trip you up :-) However, the way that I (mostly) use it, and the way that is encouraged in the documentation, is to use it like a programming language only with respect to presentation issues, not application issues. For example, using a FOREACH to calculate some sum of values is probably a Bad Thing, but using it to iterate over a data set and generate a table is a Good Thing. It a presentation loop, not a programming loop. Same goes for conditionals, and so on. Even defining the equivalent of functions or macros. If it's something that generates a presentation element and doesn't have any side effect on the application processing or underlying model then I generally think it's OK. Of course, it all depends on how you defined presentation and programming. But anyway, I'm not defending TT against HTML::Template or any other module because they admirably serve different purposes to different people at different times. TT is most definately not an enforced pure template language. You can use it that way if you like, but you can also use it as a quick, dirty and butt-ugly hacking tool. I construe that to be a good feature of a general purpose templating solution that TT aspires to be. But I also readily admit that too much freedom to Do the Wrong Thing can be a weakness in particular environments. That's why we have different modules. Sometimes you need a hammer, sometimes you need a saw, sometimes you need a socket set. Sometimes you use a wrench to bang in a nail because you can't find your hammer. That's a useful feature of a wrench, even if it's not what it was designed to do. I think the rule is: if you can solve Towers of Hanoi in the language, its general purpose enough. Indeed. And TT was designed to be general purpose enough to solve the Towers of Hanoi. I personally don't use it like that when I'm building web sites, preferring to adopt a much more rigorous coding standard, but there are also plenty of times when I do for small hacks. To solve this problem, we added a letter. bOP is MVCF, where F stands for Facade. Yep, I'm doing something that's roughly similar. Rather than have a facade which presents a collection of backend objects, I'm building what is, I suppose, a composite built from a collection of backend objects. The way our data is structured seems to favour this approach to my current way of thinking, but I will give the facade option some more thought now that you've mentioned it. But I think the concept is the same. You have some object or data structure which represents the collection of all the different components that combine to form one particular configuration of a site. This is our site model, a separate entity from our MVC, similar to your F. There are some basic design rules. Eliminating redundancy is one of them. Eliminating redundancy is another. :-) I don't see how it is an Aspect (in the capital A sense). Only really in the sense that it's an orthogonal dimension in our data space. A degree of freedom, if you like. Something that cuts across a system but needs to be defined in one place (or plane). I suspect you'll find AOP won't be in heavy use in five years except for debugging features. The magic of OO is hard enough to understand, and AOP is really magical. AOP also doesn't solve very many problems. I agree, but I found it useful in the way that it helped me to identify and put a name on a common problem. Once the lightbulb went on in my head and I said Oh, this is like the problem described in AOP then it gave me a direction to tackle it. Why is there so little discussion of the M in MVC? It's far from a trivial problem. Indeed. A
Re: Separating Aspects (Re: separating C from V in MVC)
Ow. That philosophy of 'make it impossible for the programmer to mess up' sounds too reminiscent of Pascal and other straightjacket development environments. I don't think there's any real substitute for well-disciplined, thinking programmers. So my own quest right now is to develop more of the right disciplines, rather continue on some quest for a mythical Template System to End All Template Systems or whatever. For example, you mentioned you don't like objects in templates because they introduce complexity. But others have already pointed out that objects can be used in templates as simple read-only accessors by HTML designers who don't need to know how the object is implemented. That's the great thing about encapsulation. Sure this feature could be abused, but I'd rather err on the side of freedom. --Wes Sam Tregar [EMAIL PROTECTED] on 06/05/2002 06:45:34 PM To: Andy Wardley [EMAIL PROTECTED] cc: modperl List [EMAIL PROTECTED], Template Toolkit List [EMAIL PROTECTED] (bcc: Wesley Sheldahl/Lex/Lexmark) Subject: Re: Separating Aspects (Re: separating C from V in MVC) Here's my theory: the best usage of most templating systems are virtually indistinguishable and all result in reasonably maintainable systems. However, the bad usage of some templating systems is much worse than others. Also, the general usage of a templating system, even by otherwise bright people, tends more towards the bad than the good. Thus my solution: a templating system that simply will not allow you to put anything significantly complicated in the template. You can't. If you want complexity you'll just have to put it in the code, where it belongs. That's HTML::Template in a nutshell. [% silver.bullet %] isn't the answer by itself... Here here. Neither is tmpl_var silver_bullet but I'd rather get shot with mine than yours! -sam
Re: Separating Aspects (Re: separating C from V in MVC)
Sam Tregar wrote: Now, I don't use HTML::Template::Expr. I think it's generally not such a good idea. But it's there if you want it... For posterity, and possible inclusion in the next rev of the templating tutorial, how would you recommend people handle this sort of situation without using HTML::Template::Expr? Suppose you have a model object for a concert which includes a date. On one page, the designers want to dipslay the date in a verbose way with the month spelled out, but on another they want it abbreviated and fixed length so that dates line up nicely. Would you put that formatting in the controller? What if you had a model object that generates a list of these concerts, and on a certain page the designers want to show it in two columns. Would you split it into two arrays in the controller? - Perrin
Re: Separating Aspects (Re: separating C from V in MVC)
On Thu, 6 Jun 2002, Perrin Harkins wrote: For posterity, and possible inclusion in the next rev of the templating tutorial, how would you recommend people handle this sort of situation without using HTML::Template::Expr? Suppose you have a model object for a concert which includes a date. On one page, the designers want to dipslay the date in a verbose way with the month spelled out, but on another they want it abbreviated and fixed length so that dates line up nicely. Would you put that formatting in the controller? In the script: $template-param(long_date = $long_date, short_date = $short_date); In the template: The long date: tmpl_var long_date br The short date: tmpl_var short_date What if you had a model object that generates a list of these concerts, and on a certain page the designers want to show it in two columns. Would you split it into two arrays in the controller? I'm not sure I understand what you mean. You're asking about how to flow a list between two columns? With vanilla HTML::Template that would requrie a small amount of work in the script. Either there would need to be a column_break variable thrown in at the appropriate place or two separate loops. I think I would prefer the former. In the template that would look like: tabletr tmpl_loop concerts tmpl_if column_break /trtr /tmpl_if td tmpl_var long_date /td /tmpl_loop /tr/table In the script you'd just set the column_break in the appropriate row (or rows for a multi-column layout). Is that a point in favor of scripting in the templates? Perhaps. Of course by limiting the power of template syntax I've made some things more difficult. If simple things should be simple and hard things should be possible then not everything can be simple! -sam
Separating Aspects (Re: separating C from V in MVC)
Continuing from the thread on the modperl mailing list: On Sun, Jun 02, 2002 at 05:04:01PM -0400, Sam Tregar wrote: I don't think the standard HTML::Template has support for formatting numbers, dates, etc. And thank the sweet lord it doesn't! HTML::Template is a do one thing and do it well module. If you want routines for formatting numbers, dates, etc. then CPAN has just what you need. I (mostly) consider formatting of numbers, etc., to be a presentation issue, not a programming one. That's why TT supports this kind of thing in the templates (or in the code if you prefer). Of course, the fact that it's a module/object is entirely hidden. TT abstracts the front end templates from the backend implementation, so that the HTML designers don't have to know if a data structure is implemented as a hash, object, or subroutine, it just does the right thing. This allows the developers to worry about implementing a back-end system in the best way possible and the front-end designers to just use it. HTML::Template::Expr may present a solution to this particular desire, although it isn't one I've come across. How often are HTML designers fiddling with numeric formats? Are they really HTML designers if they can deal with, say, a printf-style format string? In TT, you would usually pre-declare a particular format in a config file, pre-processed templates, or some other global style document. e.g. [% USE money = format('%.02f') %] In your main page templates you would do something like this: [% money(order.total) %] Then you can change the money format in one place and your designers don't have to worry about sprintf formats. If you prefer to write your own formatting subroutine you can do it like so: my $vars = { money = sub { return sprintf(%.02f, shift) }; order = { total = 22.95, } }; $template-process($file, $vars) || die $template-error(); Guess what? You don't have to change any of the templates. They still use the same syntax: [% money(order.total) %] This is abstraction. Not to be confused with MVC which is one particular architecture well suited to GUI applications. Blindly applying MVC without understanding the real issues (abstraction of front/back ends, separation of concerns, don't repeat yourself, etc.) is likely to build a system which is highly fragmented. Maintenance becomes harder because everything is split up into many different pieces and it becomes difficult to see the wood for the trees. Aspect oriented programming teaches us that as soon as you decompose a system into a particular structure you inevitably fragments aspects which cut across the system. I have seen this in close and painful detail over the past few months while helping to build a very strictly partitioned MVC architecture system for Fotango(.com). We're using TT for presentation, Openframe for the application pipeline/dispatch and a custom data backend called Vx. Despite our best intentions, this web site doesn't neatly fall into clearly defined chunks of model, application and view. Well, actually, those parts do split down quite nicely. But then you look at localisation, for example, and we find there is localisation required in the data backend, localisation required in the applications and localisation required in the templates. Thus, localisation is an aspect which cuts across the system. By building a strict MVC we've fragmented localisation and have to trawl through hundreds of different files to localise the site. Another example is that different countries running their localised versions of this web site will want to change the URLs. Where the english version uses /product/shirt/red.html, the french version should instead be /produit/chemise/rouge.html, for example. Again, these URLs are (currently) embedded throughout the system and making any changes to them is a painful process involved many files spread across the M, the V and the C. In an ideal world, English and French would just be different views of the same model. Alas, it's never that easy because the chances are that parts of the model and parts of the controllers will also need changing. See, the problem is that MVC is just one particular decomposition. It's generally a good one because application, data and presentation are typically the three biggest aspects that you want to separate. However, it doesn't take into account any of the other dozen or so aspects that you might want to model in your system. Nowhere in MVC or any other Design Pattern does it tell you to define all your URLs in one place in case you ever need to change them en masse. You have to think of that all by yourself. MVC is no substitute for thinking and it often encourages the opposite, lulling you into a false sense of security by the fact that you think you're doing the Right Thing. I've seen far too many example of people who didn't pass objects into
Re: separating C from V in MVC
On Thu, May 30, 2002 at 05:42:23PM -0400, Jesse Erlbaum wrote: It has been my experience that applying a design pattern such as MVC is not a panacea. [...] My point: My code isn't good because I apply some pattern to it. It may be good, and it may resemble a pattern -- but those two things are largely coincidental. Absolutely! The View, in a web application, is really the HTML output. Generally, this will be your templating system. Optimally, the View avoids *ALL* application logic. At my company we use HTML::Template because it strongly enforces the separation of View from Controller -- e.g., HTML from code. (I realize that many of you prefer other HTML templating systems, but I still contend that HTML::Template is the most effective system for truly separating HTML from code. And it's damn fast, too.) Enforcing a clear separation of View from Controller is not the same thing as not calling code from templates. It is perhaps the most misunderstood point about MVC and templates. There's nothing wrong with calling a subroutine or object method from a template as long as: * the code perform a presentation function (not an application one) * the code doesn't have any side-effects on the model or other controllers You can also call code to perform lazy data-loading as Perrin has already mentioned, but that does require a little more thought on the part of your back-end designers to ensure that things continue to behave as planned. Or you can break all the rules if you know what you're doing. I break the rules all the time when I'm knocking together a few quick and dirty web pages, generating an SQL report, or a Postscript page showing a graphical distribution of the first thousand prime numbers. MVC is good for big web sites, but overkill for quick hacks. A
Re: separating C from V in MVC
On Fri, May 31, 2002 at 12:21:45PM -0400, Jesse Erlbaum wrote: It's the addition tricks which bug me out. With those two words you establish the mother of all slippery slopes to architecture oblivion. True. And in your Perl code you can also write all sorts of dangerous code that totally breaks your MVC architecture. What stop you from doing that? IMHO, any system built on Template Toolkit (unless it is small and always managed by the same programmer) will ultimately devolve in just the same way as a Server Page system. In my experience, that's not the case. It will devolve just as fast as you allow it to. A
Re: Separating Aspects (Re: separating C from V in MVC)
On Wed, 5 Jun 2002, Andy Wardley wrote: In TT, you would usually pre-declare a particular format in a config file, pre-processed templates, or some other global style document. e.g. [% USE money = format('%.02f') %] In your main page templates you would do something like this: [% money(order.total) %] Then you can change the money format in one place and your designers don't have to worry about sprintf formats. In HTML::Template::Expr: sub money { sprintf %.02f, $_[0] } HTML::Template::Expr-register_function(money = \money); Then in the template: tmpl_var expr=money(order_total) Now, I don't use HTML::Template::Expr. I think it's generally not such a good idea. But it's there if you want it... See, the problem is that MVC is just one particular decomposition. It's generally a good one because application, data and presentation are typically the three biggest aspects that you want to separate. However, it doesn't take into account any of the other dozen or so aspects that you might want to model in your system. Nowhere in MVC or any other Design Pattern does it tell you to define all your URLs in one place in case you ever need to change them en masse. You have to think of that all by yourself. MVC is no substitute for thinking Oh, absolutely. MVC is just a framework, and it only addresses a subset of the problems in any large system. I think that's actually a strength. I would be deeply suspicious of any paradigm that claimed to solve ALL my problems. I prefer small, simple (tools|paradigms) that do one thing and do it well. I've seen far too many example of people who didn't pass objects into their templates, didn't embed Perl code, or didn't do this or that because they thought that it might violate the MVC principal. Here! The end result was that they jumped through hoops and made the system more complex than it needed to be for the sake of purity. It was? I don't think this is the only result. It might be that these people you've observed were just the hoop-jumping, complexifying types. I've built quite a number of large systems without embedded Perl and object variables without excessive hoop-jumping. Here's my theory: the best usage of most templating systems are virtually indistinguishable and all result in reasonably maintainable systems. However, the bad usage of some templating systems is much worse than others. Also, the general usage of a templating system, even by otherwise bright people, tends more towards the bad than the good. Thus my solution: a templating system that simply will not allow you to put anything significantly complicated in the template. You can't. If you want complexity you'll just have to put it in the code, where it belongs. That's HTML::Template in a nutshell. [% silver.bullet %] isn't the answer by itself... Here here. Neither is tmpl_var silver_bullet but I'd rather get shot with mine than yours! -sam
Re: separating C from V in MVC
Andy Wardley writes: Because Perl is a general purpose programming language. TT implements a general purpose presentation language. A different kettle of fish altogether. These are the reserve words of TT: GET CALL SET DEFAULT INSERT INCLUDE PROCESS WRAPPER IF UNLESS ELSE ELSIF FOR FOREACH WHILE SWITCH CASE USE PLUGIN FILTER MACRO PERL RAWPERL BLOCK META TRY THROW CATCH FINAL NEXT LAST BREAK RETURN STOP CLEAR TO STEP AND OR NOT MOD DIV END Looks an awful lot like the same keywords in any general-purpose programming language. It's like asking why XML has different syntax and semantics from Perl. Well, if you read the XSLT spec and then look at an XSLT program, you'll see a lot of verbosity and a lot of general purpose constructs like variables, conditionals, and loops. I haven't done much with XSLT, but I do know you can get it in an infinite loop. That seems pretty general purpose to me. I think the rule is: if you can solve Towers of Hanoi in the language, its general purpose enough. True formatting languages, such as, Scribe do not contain general-purpose constructs, so you couldn't solve the Towers of Hanoi. HTML is another good example (ignoring script). I find it easier to have a little language which is tailored to the task at hand. Let's separate syntax from semantics. You can use Perl syntax very easily without adopting the semantics for the little language constructs. For example, here's a bOP configuration file: { 'Bivio::Ext::DBI' = { database = 'petdb', user = 'petuser', password = 'petpass', connection = 'Bivio::SQL::Connection::Postgres', }, 'Bivio::IO::ClassLoader' = { delegates = { 'Bivio::Agent::TaskId' = 'Bivio::PetShop::Agent::TaskId', 'Bivio::Agent::HTTP::Cookie' = 'Bivio::Delegate::PersistentCookie', 'Bivio::UI::HTML::FormErrors' = 'Bivio::PetShop::UI::FormErrors', 'Bivio::TypeError' = 'Bivio::PetShop::TypeError', 'Bivio::Auth::Support' = 'Bivio::Delegate::SimpleAuthSupport', }, maps = { Model = ['Bivio::PetShop::Model', 'Bivio::Biz::Model'], Type = [ 'Bivio::PetShop::Type', 'Bivio::Type'], HTMLWidget = ['Bivio::PetShop::Widget', 'Bivio::UI::HTML::Widget', 'Bivio::UI::Widget'], Facade = ['Bivio::PetShop::Facade'], Action = ['Bivio::PetShop::Action', 'Bivio::Biz::Action'], TestLanguage = ['Bivio::PetShop::Test'], }, }, 'Bivio::UI::Facade' = { default = 'PetShop', }, 'Bivio::UI::Text' = { http_host = 'petshop.bivio.biz', mail_host = 'bivio.biz', }, }; You could use XML, Lisp, or some other syntax for this. Since the implementation of the configuration parser is in Perl, we use eval as the config parser. When I program in Lisp, I use Lisp syntax for config and eval for the parser again. The syntax is different, but the semantics probably are the same. Perrin Harkins writes: The thing that worries me about a widget approach is that I would have the same problem I had with CGI.pm's HTML widgets way back: the designers can't change the HTML easilly. Getting perl developers out of the HTML business is my main reason for using templating. I think this is where our experience diverges. I have hired designers before and every time we had to recode the HTML and the JavaScript anyway. My approach is to apply the Once And Only Once principle, which simplifies design changes (discussed more below). Andy Wardley writes: This is abstraction. Not to be confused with MVC which is one particular architecture well suited to GUI applications. Blindly applying MVC without understanding the real issues (abstraction of front/back ends, separation of concerns, don't repeat yourself, etc.) is likely to build a system which is highly fragmented. Maintenance becomes harder because everything is split up into many different pieces and it becomes difficult to see the wood for the trees. If you apply Once And Only Once extemely, you'll find that MVC is a nice fit for just about any information system. Despite our best intentions, this web site doesn't neatly fall into clearly defined chunks of model, application and view. Well, actually, those parts do split down quite nicely. But then you look at localisation, for example, and we find there is localisation required in the data backend, localisation required in the applications and localisation required in the templates. Thus, localisation is an aspect which cuts across the system. By building a strict MVC we've fragmented localisation and have to trawl through hundreds of different files to localise the site. To solve this problem, we added a letter. bOP is MVCF, where F stands for Facade. A Facade allows you to control icons, files, colors, fonts, text, and tasks. You can
Re: separating C from V in MVC
Rob Nagler wrote: The way I understand how plugins work is that they are arbitrary classes. But how do you share behavior? I probably wouldn't use a plugin for something that needed to output HTML, because that would prevent the designers from editing it. A macro (basically a mini-template) could be broken down into smaller shared templates, but there is a practical limit to that approach. FILTER does not shared behavior, but is a pipe mechanism. Yes. I think it would be a good way to do the FONT trick you mentioned though. There is no protocol for communicating between these various components except well-known global variables. That's correct. A template can call macros which are parameterized (e.g. a macro for making large text headlines which accepts the text as a parameter), but that's not exactly the same thing. If you find that you really need to have stateful widgets that share data beyond whatever model data was passed to the view, then templating is probably not an appropriate solution. For example, if a Link is not executable by the current user, it won't render as a link (and possibly be completely blank depending on the circumstance and configuration). That's easy to do, but not easy to share between multiple templates with different appearances. Another concern I have about Template Toolkit (and other template languages) is that it has its own syntax and semantics for data and control structures distinct from Perl. Why isn't Perl good enough? The syntax for accessing complex data structures in perl is non-trivial and possibly too confusing for designers. Here's the perl version: foreach my $account ( {$model_data-{'user'}-{'accounts'}} ) { and in TT: [% FOREACH account = user.accounts %] or with localized loop variables, like HTML::Template: [% FOREACH user.accounts %] My experience with little languages is that they take on a life of their own That can happen, and I've seen some people do appalling things with templating tools, but these people tend to be programmers working by themselves with no separate designer. The place where these tools really pay off is when you're working with a separate design group. My experience has been that designers have no trouble grasping the basic ideas of templating, and don't feel the need to try and wedge in stuff that doesn't belong there. The thing that worries me about a widget approach is that I would have the same problem I had with CGI.pm's HTML widgets way back: the designers can't change the HTML easilly. Getting perl developers out of the HTML business is my main reason for using templating. - Perrin
Re: separating C from V in MVC
On 6/4/02 12:32 PM, Perrin Harkins wrote: The thing that worries me about a widget approach is that I would have the same problem I had with CGI.pm's HTML widgets way back: the designers can't change the HTML easilly. Getting perl developers out of the HTML business is my main reason for using templating. My approach uses an intentionally limited subset of Mason as my templating language. It looks something like this: * Model: Regular Perl classes and objects. * Controller: Regular Perl classes and objects, trivially wrapped in Mason components to control access location (i.e. URL), object caching, and so on. * View: Mason components that receive widget-like objects as well as simple strings and other params. To try to solve the designers don't know Perl problem, I just constrain the API usage of the widget objects for designers. Example: tr td% $form-field('name')-html_label %/td td% $form-field('name')-html_field %/td /tr As concerned as I initially was by this syntax, the fact is that 99% of all view objects have a series of exactly the same calls. Designers have no clue what they do internally, but the fact is that the only part that really changes is the field name. And there are very few, simple method names to know: html_field, html_label, html_error, etc. In the simplest case, there's even a few places where this works: % $form-field('name')-html % And handles the label (if any), field, and field-tied error message all in one block. I guess the moral is that comfort != understanding. Designers can get comfortable with even ugly syntax like the above very quickly since it is repeated so often. Yes, this means that all the nuts and bolts of what gets printed by those calls is handled by the controller object (which produces the widgets, populating them according to the data form the model objects), and therefore the programmer. But IMO this is as it should be. The programmer flags which form fields are required, what HTML surrounds error messages (usually just span class=error) and so on. The designers change the contents of the style sheets, make the graphics, and arrange the widgets on the page. And in a pinch, the programmer does have the full range of Mason features available. IMO, it's not much harder for designers to learn some small subset of a larger syntax (like Mason/Perl-Widget-API) than it is for them to learn an equal size subset (or entirety) of a little language like template toolkit. -John
Re: separating C from V in MVC
Perrin Harkins writes: You can actually do that pretty comfortably with Template Toolkit. You could use a filter for example, which might look like this: [% FILTER font('my_first_name_font') %] ... some text, possibly with other template directives in it... [% END %] One of the reasons Perl is popular is its idioms. Having to say something in three lines is not as idiomatic as one line. It takes a lot of discipline to use it everywhere. In other words, I don't think the above is more comfortable than: String(['User.first_name'], 'my_first_name_font'); Note also the accessor for User.first_name in Template Toolkit is probably nontrivial. Rob
Re: separating C from V in MVC
On Mon, 3 Jun 2002, Rob Nagler wrote: Date: Mon, 3 Jun 2002 08:09:12 -0600 From: Rob Nagler [EMAIL PROTECTED] To: [EMAIL PROTECTED] Subject: Re: separating C from V in MVC Perrin Harkins writes: You can actually do that pretty comfortably with Template Toolkit. You could use a filter for example, which might look like this: [% FILTER font('my_first_name_font') %] ... some text, possibly with other template directives in it... [% END %] One of the reasons Perl is popular is its idioms. Having to say something in three lines is not as idiomatic as one line. It takes a lot of discipline to use it everywhere. In other words, I don't think the above is more comfortable than: String(['User.first_name'], 'my_first_name_font'); Note also the accessor for User.first_name in Template Toolkit is probably nontrivial. Rob Not to see this discussion devolve into Yet Another Template War, but there's more than one way to do filters in Template Toolkit: [% User.first_name | my_filter %] Add to the handy pipe syntax the number of built-in filters (esp. the html and uri ones), and you get a large amount of convenience because you don't have to pre-format your data before passing it to a template (which seems to more strongly couple to the C to the V). It's just my opinion, baby, I may be right or wrong. -- Robert Johnson ky
Re: separating C from V in MVC
Rob Nagler wrote: Perrin Harkins writes: You can actually do that pretty comfortably with Template Toolkit. You could use a filter for example, which might look like this: [% FILTER font('my_first_name_font') %] ... some text, possibly with other template directives in it... [% END %] One of the reasons Perl is popular is its idioms. Having to say something in three lines is not as idiomatic as one line. It takes a lot of discipline to use it everywhere. In other words, I don't think the above is more comfortable than: String(['User.first_name'], 'my_first_name_font'); The advantage is that my example can contain other templating code: [% FILTER font('basic_info_font') %] Hello [% User.first_name %]!BR [% IF User.accounts %] You have these accounts:BR [% FOREACH User.accounts %] [% name %]: [% balance %]BR [% END %] [% END %] [% END %] Unless I'm missing something about your example, the FILTER concept seems more powerful. It is perfectly possible to simply add a plugin to TT to make it look like yor example though: [% String(User.first_name, 'my_first_name_font') %] Note also the accessor for User.first_name in Template Toolkit is probably nontrivial. Assuming it's just $User-first_name() and you passed in $User as part of your data to the view, there's no additional work. - Perrin
Re: separating C from V in MVC
I really enjoyed this topic... I hope you guys are planning on actually documenting your ideas. I would love to read and learn more about this topic. -r
Re: separating C from V in MVC
Perrin Harkins writes: The advantage is that my example can contain other templating code: [% FILTER font('basic_info_font') %] Hello [% User.first_name %]!BR [% IF User.accounts %] You have these accounts:BR [% FOREACH User.accounts %] [% name %]: [% balance %]BR [% END %] [% END %] [% END %] Unless I'm missing something about your example, the FILTER concept seems more powerful. [Skirting on the edge of YATW. :-] I think they are equivalent as far as power. I go back to why people use Perl, because it makes the easy jobs easy and the hard jobs possible. All programming languages are Turing Complete, but we don't like programming Turing Machines. Here's your expanded example in widgets: String(Prose('EOF'), 'basic_info_font'); Hello String(['Model.User', 'first_name']);!br If(['Model.AccountList', '-get_result_set_size'], Join([ You have these accounts:br, Table('Model.AccountList', [ 'name', 'balance', ]), ]), ); EOF The Table widget will print a table with headings defined by the Facade (our term for skin). The widgets for name and balance are looked up dynamically. balance will be right adjusted. Unless I missing something, the template example won't align properly in HTML. This is a significant semantic difference between FOREACH and Table. Would you expand on the example so that name and balance are columnar? Rob
Re: separating C from V in MVC
Rob Nagler wrote: [Skirting on the edge of YATW. :-] I certainly don't mean to have a templating war. I'm just trying to figure out what the difference is between these approaches and if there's something I've been missing that I should consider adding to future applications. Here's your expanded example in widgets: String(Prose('EOF'), 'basic_info_font'); Hello String(['Model.User', 'first_name']);!br If(['Model.AccountList', '-get_result_set_size'], Join([ You have these accounts:br, Table('Model.AccountList', [ 'name', 'balance', ]), ]), ); EOF If your String widget can accept other widgets recursively like this, then our examples are equivalent. I thought it was limited to a simple value. Unless I missing something, the template example won't align properly in HTML. This is a significant semantic difference between FOREACH and Table. I just didn't put in any fancy HTML in my example. I could have put in table tags right there, or made a macro if that table gets repeated a lot. Looks to me like they work the same. In TT, I would probably use macros or small templates (possibly defined in this same template file at the top) for little repeating chunks, and filters or plugins for things with more brains, like the String widget that decides whether or not it needs to print FONT tags. - Perrin
Re: separating C from V in MVC
On Sat, 1 Jun 2002, Barry Hoggard wrote: I don't think the standard HTML::Template has support for formatting numbers, dates, etc. And thank the sweet lord it doesn't! HTML::Template is a do one thing and do it well module. If you want routines for formatting numbers, dates, etc. then CPAN has just what you need. How do you make sure that it's done consistently in your applications? Code reviews and testing. I don't know of any other way, module support or no module support. It seems problematic to me to require the programmers to do work when a designer wants to change the number of decimals in a page, for example. HTML::Template::Expr may present a solution to this particular desire, although it isn't one I've come across. How often are HTML designers fiddling with numeric formats? Are they really HTML designers if they can deal with, say, a printf-style format string? -sam
Re: separating C from V in MVC
It seems problematic to me to require the programmers to do work when a designer wants to change the number of decimals in a page, for example. HTML::Template::Expr may present a solution to this particular desire, although it isn't one I've come across. How often are HTML designers fiddling with numeric formats? Are they really HTML designers if they can deal with, say, a printf-style format string? Yes, they are, and printf isn't so much harder than JavaScript, style sheets, and templating tags. One place where this comes up is date formatting and internationalization. Making the model objects understand locale and act appropriately is not always a good approach, and supplying a date format in the template - which is all about appearance anyway - seems appropriate. This can also be useful when the same date needs to be displayed in multiple ways, like an abbreviated format on one page and a fixed length format in an e-mail template. You could make the controller do this sort of formatting before passing data off to the view, but I think it's an awkward fit and increases the coupling between components unnecessarilly. Obviously there are lots of ways to solve these problems, but what I like about doing it in the template is that it puts these concerns in the hands of the people who control the rest of the look-and-feel issues in the application, and gets them out of the perl programmers' way. - Perrin
Re: separating C from V in MVC
It is interesting to try and fit our approach into the MVC+template pattern Just to clarify, it's not MVC+template; it's just MVC. The templates are one way of implementing views. You could mix and match this where appropriate, so that your Excel view is a perl module with a set of formatting guidelines stored in a sort of style sheet, while your HTML view is simply a template executed by a templating module. I see the Controller as also responsible for deciding what to do with the results of rendering the DOM in Excel or HTML formats - Views don't decide how their results should be distributed. This is typically something you would put into the controller, since the view shouldn't have to worry about details like HTTP headers. - Perrin
Re: separating C from V in MVC
A String widget/template allows you to control the rendering of all fonts dynamically. If the String widget/template sees the incoming request is from IE5+, it doesn't render the font if the font is the same as the default font. The Style widget/template renders the default font in a style if the browser is IE5+. This avoids the stylesheet bugs in all other browsers and gives 90% of your users who are running IE5+ a much lighter weight page. It's cumbersome to do wrap all text in string templates, because the calling mechanism is verbose. Most template languages I've looked at only support named parameters. Widgets can have named parameters, e.g. String({ value = ['User.first_name'], string_font = 'my_first_name_font', }); but it is much more convenient to use positional notation: String(['User.first_name'], 'my_first_name_font'); You can actually do that pretty comfortably with Template Toolkit. You could use a filter for example, which might look like this: [% FILTER font('my_first_name_font') %] ... some text, possibly with other template directives in it... [% END %] The filter is a module which would get to post-process the output of the contained block. I believe the taglibs in AxKit could be used in a similar way. - Perrin
RE: separating C from V in MVC
From: Jesse Erlbaum [mailto:[EMAIL PROTECTED]] Sent: 30 May 2002 22:42 To: 'Ray Zimmerman'; modperl List; Mason List Jesse, thanks for your comments, I found them very interesting. I am comfortable with Perl and Web programming (though previously not the two together) and am about to embark on development of a new product for an ASP, so have considerable interest at this stage of the proceedings. I would like to ask some further questions, please forgive the extensive haircut of your comments: applying a design pattern such as MVC is not a panacea I agree - I much prefer Perlish DWIM dweomer Model: The business logic. Not related to the UI at all. View: The user interface. Controller: The glue between the View and the Model. ... the Model is simply a Perl module... make it entirely separate from the user interface... the methods... being called from a web application, a cron script, or an email-based interface Makes sense, in old-style speak [yes, I am approaching 'Ancient of Days' status] this seems to indicate the Model accepts method calls and returns data that will be rendered elsewhere. In our planned development, there is a LOT of tabular data - do you use any standards for the data being returned to the Controller? eg do you use a struct [ie hash/array Perl primitive] or do you return an object? eg a table object etc? The View, in a web application, is really the HTML output. Sounds good, so I could also pass the Models returned data to a different flavoured rendering view eg PDF, Spreadsheet, Text etc. This sounds a lot like our existing Perl reporting infra which does exactly that. W3 did a huge amount of analysis on layout and style as part of the CSS specs. In our setup, the table objects contain lots of style info. It is easy to render complex tables in PDF [as HTML will be] but formats like Excel are very hard, as there are layout constraints [eg a column can have only one width for the entire page - we call this the 'Highlander Effect'] Is this true of your setup? does the Model returned data contain lots of style hints? Or do you leave this completely to the View layer? How does the view layer know for example to render an Error cell as RED in HTML but blue in Excel due to Excel palette limitations? Optimally, the View avoids *ALL* application logic. - so the Model has to say RED rather than ERROR? but that wouldn't work if rendering something where RED is illegible? Our reporting knows about basic things like Error, Good, User Date / Numeric preferences etc. At my company we use HTML::Template ... it's damn fast, too will look at this - is there a list somewhere? The Controller connects the View to the Model... takes user input ... translates it into method calls on the Model... then takes output from the Model and passes it to your View. Sounds like Controller only interacts with one Model? I would assume that a Controller might collect data from a number of Models, and then pass the collection of data to a View? What controls the overall layout? e.g. what is the equivalent of the 'Grid Bag' layout manager - is this done in the Controller? and then passed to the View with all the data from a set of Models? Or do you make the Controller minimalist and have a meta-Model that assembles all the sub-Models into a layout. CGI::Application modules will do some reading on this also then. separating the View from Controller is a problem. I guess this is a balance between purist and DWIMism, but as we already have this separation for reporting, I would like to extend it into our dynamic web page generation. If you have to work with an SPS such as Mason but you still want to separate your View from your Controller, you have to work twice as hard. Interesting! Jesse, I found your posting extremely useful - thank you very much! Regards Jeff
RE: separating C from V in MVC
From: Perrin Harkins [mailto:[EMAIL PROTECTED]] Sent: 01 June 2002 00:17 To: Rob Nagler Cc: [EMAIL PROTECTED] The same template? How does the layout manager help with that? Does it modify the template? It would make more sense to me if this were a sort of abstraction to factor out common layout ideas from multiple templates. The layout manager is more complex than a static template. It takes a collection of data and meta-data and creates a document tree that is not a specific rendering flavour - the DOM might subsequently be rendered in NS4.0 HTML, IE5.01+ HTML, Excel, PDF etc. without requiring (every page) x (every format) x (every option) templates. ... That doesn't require a layout manager though. Simple templating is fine for that, i.e. two different templates (views). In most circumstances it is ok to have templates that are specific to one output flavour, possible with some simple alts. But what if I have 40 pages that I want to render in: IE5+HTML, NS4-HTML, Excel, HP-PCL5 and PDF - and I also want SIMPLE views of each page. This would result in 40 x 5 x 2 = 400 templates. For every change in a basic page, I have to keep 9 other templates in other languages in step. If the number of output formats and page variants is not trivial, it might make more sense to have an active component that creates the document tree, and passes it to simple components that know how to render a DOM in the desired output format. All in all, I think the MVC+template approach described is fine for most of the type of dynamic sites currently available on the web. But I work for a small ASP and we have to manage rapidly changing complex dynamic sites and complex user reporting requirements, with minimal work. We don't have any HTML specialists, but rather a few very good technical generalists. I think that for us a meta-data layout driven approach will be more effective. We do however plan to borrow all the good ideas we can find from any other model, including MVC+template. Our planned move to mod_perl is mostly due to the benefits we have seen from out Perl data processing and reporting - hence the desire to join both the web and DP infra at the hip. Regards Jeff
RE: separating C from V in MVC
At 15:09 01.06.2002, Jeff wrote: From: Perrin Harkins [mailto:[EMAIL PROTECTED]] Sent: 01 June 2002 00:17 To: Rob Nagler Cc: [EMAIL PROTECTED] The same template? How does the layout manager help with that? Does it modify the template? It would make more sense to me if this were a sort of abstraction to factor out common layout ideas from multiple templates. The layout manager is more complex than a static template. It takes a collection of data and meta-data and creates a document tree that is not a specific rendering flavour - the DOM might subsequently be rendered in NS4.0 HTML, IE5.01+ HTML, Excel, PDF etc. without requiring (every page) x (every format) x (every option) templates. Well, as I see this, it isn't a problem. The layout manager takes the place of the view, as it essentially decides how things should be rendered. You then have two stages in your view, but the same techniques apply (as the 2nd stage of the view isn't really specific to any model or controller). -- Per Einar Ellefsen [EMAIL PROTECTED]