Mark - I'm sending this to the list because your address bounced. - Rob
-----Original Message-----
From: Kinyon, Rob
Sent: Wednesday, June 30, 2004 2:28 PM
To: 'Mark Fuller'
Subject: RE: Spam:Re: [cgiapp] Teardown cleanup
Mark -
Those are actually good points you bring up re: reuse. However,
I think you're looking at it slightly askew. Just because there happens
to be 100 ways to do something doesn't mean that you can't just pick one
and go with it. So what if another is "better" (for some value of
better)?? If what you have is good enough, then it's good enough. If
it's not good enough, you pick another way.
Another way to look at it is that there's often different types
of solutions to the same problem. HTML::Template and Template Toolkit
are a good example. H::T provides speed, but few features, and it's
easier to work with. TT provides a ton more features, but the learning
curve is higher and there's a (small) performance penalty. Depending on
which set of features you're looking for, you pick one or the other.
Also, one solution may be a wrapper around another solution. For
example, Excel::Template is a wrapper around Spreadsheet::WriteExcel.
You would use the one that's easier for you to use. For some, it's E::T.
For others, it's S::WE. *shrugs* It's still re-use.
As for "require" ... they won't be loaded pre-forking because
your CGI script isn't called pre-forking. Now, if you have it in a
CGI::Application child, it might be (assuming you have your C::A classes
in your startup.pl), but require is still less useful than packages. In
fact, I just gave a talk on this about 10 minutes ago to developers in
my group. The difference is namespaces. You'll want to have a class that
wraps around DBI, not a Perl script that contains functions to deal with
DBI. The former is a cleaner and more extensible way to do it. If you
don't see why, try it out.
As for "global variables" ... I would strongly recommend using
the param method. It's C::A's way of doing setters/getters. The main
reason for this is because you can now inherit from your C::A class and
everything will just flow through. See my replies to
http://www.perlmonks.org/index.pl?node_id=320933. (I'm dragonchild).
"our" will prevent your children from accessing those variables
without explicitly knowing where they live. Assigning to the $self
variable directly assumes you know what kind of reference $self is. What
if the maintainer(s) decide to shift from HASH to ARRAY (as most of my
objects are) or even SCALAR (to use inside-out objects)? All your code
breaks.
These are hard concepts to wrap your head around, when you're
used to thinking a certain way. Let them simmer for a bit. And, feel
free to ask me any questions you might have. :-)
Rob
-----Original Message-----
From: Mark Fuller [mailto:suppressed
Sent: Wednesday, June 30, 2004 1:35 PM
To: Kinyon, Rob
Subject: Spam:Re: [cgiapp] Teardown cleanup
Thanks Rob. I'm not replying to the list since 1) I'm probably getting
off
topic, and 2) most people probably know the answer to this last
question.
If my requires are at the top of my program, won't the required code be
loaded prior to forking? (the same as a module)?
One thing I've been struggling with is whether, in my cgi::app webapp,
whether to use 1) "our" variables for my global variables, 2) add them
to
$self, or 3) use the param method. I don't really understand the
choices.
Not to be a smart-alec, but this is one reason I don't completely agree
with
the standard module (reuse) reasoning. If reuse and minimizing developer
time were as important as most people say (and I tend to agree), Perl
wouldn't provide 18 ways to do something. It would be more like pascal.
Or,
we'd all be using Python. :) I'm not trying to be a smart ass. I'm just
saying that using perl and at the same time striving for
reuse/standardization/minimal developer expense seems like a
contradiction
to me.
I like Perl. But, just in my own mind, if I really got on the modular,
object oriented, reuse bandwagon, I'd probably look to do it in a
language
that enforces more structure/standardization. Maybe I'm all wrong.
That's
just how I think about it.
Thanks!
Mark
----- Original Message -----
From: "Kinyon, Rob" <suppressed>
To: "Mark Fuller" <suppressed>
Cc: <suppressed>
Sent: Wednesday, June 30, 2004 6:15 AM
Subject: RE: [cgiapp] Teardown cleanup
Mark -
I'll address your concerns in order.
1) The primary benefit of packages is another namespace. What this means
is that you can have function foo() in your script and function foo() in
your package. As long as your package isn't called 'main', you have a
unique name for each foo(). This means you don't have to know what's
going on under the hood in the package to make sure you don't
accidentally clobber a name it's depending on.
The secondary benefit is that packages are how Perl5 does OO. But,
that's irrelevant to some people.
Under mod_perl, putting it into a package allows you to load the code
prior to the Apache server forking. This means that the time to serve a
given request is shorter and the memory needed per child process is
smaller, because the code has already been loaded and is being shared
with each child. So, the more code you can load pre-fork, the faster
each process will run and the more processes you can have running at the
same time. I've seen some statistics where taking a bunch of require'd
code and converting it to packages allowed for a 50%+ improvement in
response time and the ability to have 2-3x as many simultaneous requests
handled.
2) Most of the rest of your statements, in my opinion, fall under the
"premature optimization" category. Have you benchmarked Apache::DBI to
determine if it's too slow? Note that I didn't say "slower", but "too
slow". If your method takes 1ms and Apache::DBI takes 2ms, it's obvious
yours is faster. But, it's also obvious (to me) that the difference is
completely irrelevant. And, since your method requires more of your
developer time, Apache::DBI looks (to me) to be the overall win.
Remember - hardware is faster than software. Hardware capability
improves expontentially and software capability increases linearly.
Developer time is now the most expensive portion of a piece of software.
Minimizing the amount of time you have to spend working on a piece of
software is the quickest way to minimize the cost of that software.
Additionally, you minimize your risk. The number of bugs in your
software increases with the number of lines you write. If you could
replace a chunk of your code with a chunk that's been battle-tested in
thousands of other places, wouldn't that be better? In my opinion, I
would prefer to take a minor execution hit that my users will never be
aware of to reduce the overall complexity of what I personally have to
maintain.
Now, if you wanted to contribute your design back to the maintainers of
Apache::DBI, that would be a strong benefit to the community as a whole.
You get the benefit of using proven software and we get the benefit of
an improved design. And, if the design is not better than what's in
Apache::DBI, you not only learn why, but you *still* get the benefit of
proven software.
Thanks,
Rob
P.S. - have you even read the source for Apache::DBI? You mention having
read articles, but there's nothing like reading the source to understand
something.
-----Original Message-----
From: Mark Fuller [mailto:suppressed
Sent: Sunday, June 27, 2004 7:55 PM
To: Thilo Planz; suppressed
Cc: suppressed
Subject: Re: [cgiapp] Teardown cleanup
From: "Thilo Planz" <suppressed>
>
>So what I usually do here is make packages
That makes sense. I put my database stuff in "db.pl" and require it. So,
what's the advantage of putting it in db.pm as a package. I've never
quite
understood why packages are preferred. To me, it seems like requiring a
.pl
library and calling subroutings passing parameters by reference (to be
modified in the subroutine) would be more efficient than what I *think*
is
happening in packaged modules. So far I've not noticed any negatives
using
.pl libraries.
From: suppressed
>
>under mod_perl if you use Apache::DBI then it will transparently cache
your
database connections
I read on Perl Monks (maybe where my questions belonged) there are some
downsides to Apache::DBI. I read in another article that Apache::DBI
pings
the database connection prior to each use. And, And it checks for a
cached
prepared-statement before each use.
I came up with my own connection manager which assumes the connection is
up
and the statement is prepared. In other words, it goes into connect mode
and
prepare mode only after a failed database operation (executed within an
eval). I thought this kind of exception processing would be more
efficient
than (if I understood correctly) Apache::DBI's treating all access as
exceptional (looking for an already used statement handle, pinging the
connection).
My dbh_handler subroutine is called *only after* a failed access. My
statement handles are in a hash. A "db_active" boolean helps me know,
after
a failure, whether I expect dbh to be connected or not. It's basic
logic:
1. If not db_active, connect and prepare the sth_hash{name} that just
failed.
2. If db_active, and sth_hash{name} is undefined, prepare it.
3. Otherwise, it was a real failure. Call a subroutine to disconnect
from
the database, set db_active to false, undef everything in %sth_hash (in
preparation for the next retry to start fresh).
My code performs SQL in a while (!some_subroutine()) loop. It will retry
the
SQL some configurable number of times. "Some_subroutine" executes $sth->
within an eval. If $@ (result of the eval), it calls the dbh_handler
passing
it (by reference) the dbh, sth_hash, statement name and a coderef to the
prepare subroutine.
It works ok for me. It puts all the DB handling after an error. It
otherwise
expects everything to work well and doesn't do any testing prior to
executing database stuff. I can share examples if anyone wants it. It's
just
an sth prepare subroutine (for each statement handle). A select (or
insert,
update, whatever) subroutine for each sth. And, the dbh_handler error
subroutine which handles 3 possible conditions.
Mark
CONFIDENTIALITY NOTICE: The information in this electronic transmission
and
any documents accompanying it may contain confidential information
belonging
to the sender, which is legally privileged. The information is intended
only for the use of the individual or entities named above. If you are
not
the intended recipient, you are hereby notified that any disclosure,
copying, distribution or the taking of any action in reliance on the
contents of this information is strictly prohibited. If you have
received
this transmission in error, please destroy the message in its entirety.
---------------------------------------------------------------------
Web Archive: http://www.mail-archive.com/suppressed/
http://marc.theaimsgroup.com/?l=cgiapp&r=1&w=2
To unsubscribe, e-mail: suppressed
For additional commands, e-mail: suppressed
CONFIDENTIALITY NOTICE: The information in this electronic transmission and any documents accompanying it may contain confidential information belonging to the sender, which is legally privileged. The information is intended only for the use of the individual or entities named above. If you are not the intended recipient, you are hereby notified that any disclosure, copying, distribution or the taking of any action in reliance on the contents of this information is strictly prohibited. If you have received this transmission in error, please destroy the message in its entirety.
---------------------------------------------------------------------
Web Archive: http://www.mail-archive.com/suppressed/
http://marc.theaimsgroup.com/?l=cgiapp&r=1&w=2
To unsubscribe, e-mail: suppressed
For additional commands, e-mail: suppressed
Mail converted by mhonarc 2.6.15
This archive provided courtesy of JSW4.NET, Internet Hosting Services for Small Business.