> I want to make web programmer's life easy. I want she just *uses* what she
> needs, without caring about *loading* it. Of course, this is the ideal case, 
> and
> I'm trying to achieve that stepwise.
> 
> Let's assume there are db facilities in a ::Db namespace. The framework itself
> doesn't need them to work, so it doesn't load them in order to save time and
> memory.
> 
> Soon or later, after the framework is ready, a user code will be run depending
> on the request. Let's suppose that code *needs* the db stuff, so there could 
> be
> a line such
> 
>    Db::query "sql query"
> 
> Here, Db::query is not known, the ::unknown proc will be called, and there 
> magic
> happens: the framework-provided ::unknown finds that Db is a known subsystem,
> it finds the right file containing it, it sources that file, making
> the Db namespace available; then it could call some initializing proc, such as
> ::Db::init, and finally, it retries the Db::query call.


You should have led with this in your initial inquiry. :)  The problem with 
asking, "how do I do X" instead of "I'm trying to do X, what is the best way" 
is that sometimes your question gets answered without actually giving the RIGHT 
answer.

In this case, Tcl already does what you want.  It's called auto_load.  Rivet 
already uses it for all of the commands in the rivet-tcl directory like parray 
and such.  Those bits of code are not loaded with each interpreter, they are 
only sourced in the first time you attempt to use them.  You can find the docs 
here:

http://www.tcl.tk/man/tcl8.6/TclCmd/library.htm

You don't need to reinvent what Tcl already does here.  In fact, Tcl itself 
uses the auto_load capabilities for a lot of things.  Open up tclsh and parray 
the ::auto_index array.  You'll find a bunch of stuff in there.

All that being said, it may be a better idea to be explicit.  Instead of 
auto-loading the DB code the first time the call is made, you make the 
developer add:

package require framework::db

to get the DB package loaded.  Whether or not you do it explicitly or magically 
is purely up to you.  Some would argue for either way, and I don't have a 
specific opinion.  Just pointing it out. 0-]

Also, just to note, before you go renaming ::unknown out of the way, you should 
read up on the [namespace unknown] command.  You can actually specify your own 
unknown handler for every single namespace in Tcl and then let them roll back 
to a higher-level handler or eventually down to ::unknown itself.  Check the 
namespace docs.


>> I probably should do something like I've just suggested to you and open up 
>> my work
>> for everyone to criticize it
> 
> It would be very nice, expecially to see other implementations in the
> area of security and user input handling.
> 
>> My hope is simple, that we can end up having something flexible and light 
>> enough
>> to be easily stretched to be reused in the many cases where one needs to
>> create a web interface to some application.
> 
> Definitely agree, it is a strong requirement for making Tcl compete with other
> solutions and increase its usage base.


I'm sure you'll find nearly everyone on this list has written a Tcl / Rivet 
framework of some kind at some point, myself included.  I have a really nice 
little framework I use for my web apps, but I've never shared or released it 
because I don't want to support it / update it for a bunch of other people.  
That said, I will offer a few notes before you tilt at this windmill. 0-]

1.  Don't worry about objects.  Everyone loves OOP, that's cool, but you don't 
need it here.  At least not a parent, singleton object for each request.  You 
already have that, it's called the ::request namespace.  Rivet builds it, 
executes in it, and destroys it with every request.  Creating an object on top 
of that just to run your framework is overkill.

2.  Like you've already decided, keep the bits separate.  I have the main 
framework, a DB package and a  UI package (for forms and other bits of web UI 
sundry) all in packages that you can choose to use or not choose to use.  Cuts 
way down on load times.

3.  Initialize your framework in the global namespace one time using the 
package mechanism, then you don't have to incur that cost with each request.  
ESPECIALLY in production code.  I built a debug variable in which says that I'm 
in a "dev" instance of the framework, and in dev mode the entire framework is 
reloaded with each request.  This is for me when I'm developing the framework 
and other bits.  I want to reload each time to make sure my changes are in.

That's all I can think of in a few minutes. 0-]

Damon
---------------------------------------------------------------------
To unsubscribe, e-mail: [email protected]
For additional commands, e-mail: [email protected]

Reply via email to