PageRenderTime 45ms CodeModel.GetById 20ms RepoModel.GetById 0ms app.codeStats 0ms

/lib/App/quickstart.pod

https://github.com/gitpan/App-Context
Perl | 424 lines | 375 code | 40 blank | 9 comment | 7 complexity | d4398a45ef3ccb1ad02a523f2b980a31 MD5 | raw file
  1. #!perl -w
  2. # run this document through perl to check its syntax
  3. use Pod::Checker;
  4. podchecker(\*DATA);
  5. __END__
  6. =head1 NAME
  7. App::quickstart - App::Context Developer's Quick-Start Guide
  8. =head1 INTRODUCTION
  9. This is the Developer's Quickstart Guide to the App::Context Framework.
  10. Its focus is to give a minimum amount of theoretical or explanatory
  11. background and get right into learning by example.
  12. =head1 DOCUMENTATION OVERVIEW
  13. That having been said, it is also important to let you know
  14. what documentation exists and what state it is in.
  15. I got started building the App::Context framework a while ago.
  16. The documentation is very limited. This is an effort to bring it all together.
  17. This list shows how all of the documentation fits together and in what state
  18. it is.
  19. =head2 PURE DOCUMENTATION
  20. The following documentation is in good shape.
  21. To get started, read them more or less in the order shown.
  22. =over
  23. =item * L<App::quickstart> - This quick start guide.
  24. =item * L<App::installguide::hosted> - Installing the App::Context Framework on a non-root web hosting account
  25. =back
  26. The following documentation also is in good shape.
  27. It is background reference material.
  28. =over
  29. =item * L<App::datetime> - Guidance on date, time, and datetime types in perl.
  30. =item * L<App::exceptions> - Guidance on exceptions in perl.
  31. =back
  32. The following documentation is in a state that needs review, modification, or completion.
  33. =over
  34. =item * L<App::perlstyle> - A perl style guide that builds minimally on L<perlstyle>.
  35. =item * L<App::faq> - Questions about P5EE.
  36. =item * L<App::installguide> - Installing the App::Context Framework on Unix.
  37. =item * L<App::installguide::win32> - Installing the App::Context Framework on Windows.
  38. =item * L<App::devguide> - Developers' Guide.
  39. =item * L<App::devguide> - Developers' Guide.
  40. =item * L<App::adminguide> - Administrators' Guide.
  41. =item * L<App::adminguide::cvs> - Admin Guide, setting up CVS source control.
  42. =back
  43. =head2 CLASS/MODULE DOCUMENTATION (indented entries are subclasses)
  44. Most of this documentation needs review, modification, and completion.
  45. =over
  46. =item * L<App> - The module that bootstraps the use of the App::Context Framework.
  47. =item * L<App::Context> - Abstract class representing the the runtime context of the program.
  48. =item * +-- L<App::Context::Cmd> - A program running in a command-line context.
  49. =item * +-- L<App::Context::HTTP> - A program running in a CGI/mod_perl context.
  50. =item * +-- L<App::Context::Server> - A program running in a multi-process server context.
  51. =item * =====+-- L<App::Context::ClusterController> - Running in a multi-node cluster context.
  52. =item * =====+-- L<App::Context::ClusterNode> - Running on a single node of a cluster.
  53. =item * +-- L<App::Context::NetServer> - Another flavor of server context (not yet implemented).
  54. =item * L<App::Exceptions> - Defines the exceptions used in the framework.
  55. =item * L<App::UserAgent>
  56. =item * L<App::Request>
  57. =item * +-- L<App::Request::CGI>
  58. =item * L<App::Response>
  59. =item * L<App::Session>
  60. =item * +-- L<App::Session::HTMLHidden>
  61. =item * +-- L<App::Session::Cookie>
  62. =item * L<App::Reference>
  63. =item * +-- L<App::Conf>
  64. =item * =====+-- L<App::Conf::File>
  65. =item * L<App::Service>
  66. =item * +-- L<App::Serializer>
  67. =item * =====+-- L<App::Serializer::Properties>
  68. =item * =====+-- L<App::Serializer::Ini>
  69. =item * =====+-- L<App::Serializer::Perl>
  70. =item * =====+-- L<App::Serializer::Xml>
  71. =item * =====+-- L<App::Serializer::Yaml>
  72. =item * =====+-- L<App::Serializer::OneLine>
  73. =item * =====+-- L<App::Serializer::TextArray>
  74. =item * =====+-- L<App::Serializer::Storable>
  75. =item * +-- L<App::SessionObject>
  76. =item * +-- L<App::Authentication>
  77. =item * +-- L<App::Authorization>
  78. =item * +-- L<App::ValueDomain>
  79. =item * +-- L<App::SharedDatastore>
  80. =item * +-- L<App::MessageDispatcher>
  81. =item * +-- L<App::CallDispatcher>
  82. =item * =====+-- L<App::CallDispatcher::HTTPSimple>
  83. =item * +-- L<App::ResourceLocker>
  84. =item * =====+-- L<App::ResourceLocker::IPCSemaphore>
  85. =item * =====+-- L<App::ResourceLocker::IPCLocker>
  86. =item * L<Apache::Framework::App>
  87. =back
  88. =head1 INSTALLATION
  89. You can go through one of the installation guides.
  90. Installing the App::Context Framework generally involves several distributions
  91. and should just work when installed from CPAN.
  92. perl -MCPAN -e shell
  93. cpan> install App::Options
  94. cpan> install App::Context
  95. cpan> install App::Repository
  96. cpan> install App::Widget
  97. cpan> exit
  98. If it's not this easy, I need to work on making it easier.
  99. Please let me know (spadkins@gmail.com) and I'll fix it.
  100. =head1 QUICK START TO COMMAND LINE DATABASE PROGRAMS
  101. One of the big advantages of using the App::Context Framework for
  102. command-line programs is in developing a suite of database programs
  103. (particularly for a MySQL database).
  104. Choose a root directory for your system, assigning it to the PREFIX variable.
  105. vi ~/.bash_profile
  106. export PREFIX=/usr/mycompany/prod
  107. vi $PREFIX/etc/app.conf
  108. dbhost = localhost
  109. dbname = test
  110. dbuser = scott
  111. dbpass = tiger
  112. vi $PREFIX/etc/app.pl
  113. $conf = {
  114. Repository => {
  115. default => { alias => "db", },
  116. db => {
  117. class => "App::Repository::MySQL",
  118. },
  119. },
  120. };
  121. vi $PREFIX/bin/prog
  122. #!/usr/bin/perl -w
  123. use strict;
  124. use App::Options (
  125. options => [qw(dbhost dbname dbuser dbpass)],
  126. option => {
  127. dbhost => {
  128. description => "database host",
  129. required => 1,
  130. },
  131. dbname => {
  132. description => "database name",
  133. required => 1,
  134. },
  135. dbuser => {
  136. description => "database user",
  137. required => 1,
  138. },
  139. dbpass => {
  140. description => "database password",
  141. required => 1,
  142. },
  143. },
  144. );
  145. use App;
  146. use App::Repository;
  147. {
  148. my $context = $App->context();
  149. my $db = $context->repository();
  150. # perform database ops like ...
  151. # my $rows = $db->get_rows("customer", { last_name => "Smith" }, ["first_name", "last_name", "birth_dt"]);
  152. # my $hashes = $db->get_hashes("customer", { "birth_dt.le" => "2000-01-01" }, ["first_name", "last_name", "birth_dt"]);
  153. # my $age = $db->get("customer", { customer_id => 45 }, "age");
  154. }
  155. The best parts about writing database programs with App::Repository in the App::Context framework
  156. is that all of your programs get automatic SQL debugging, timing, and explaining.
  157. prog --debug_sql # show all SQL statements and their timings
  158. prog --debug_sql=2 # show all SQL statements and their timings and all rows returned from selects
  159. prog --debug_sql --explain_sql # show SQL statements and explain them
  160. See L<App::Options>, L<App::Repository::quickstart>, and L<App::Repository::devguide> for more info on this.
  161. =head1 QUICK START TO OBJECT-ORIENTED COMMAND LINE PROGRAMS
  162. Another of the big advantages of using the App::Context Framework for
  163. command line programs is in developing programs which use and operate on Business Objects
  164. (the object-oriented analysis concept, not the commercial reporting software).
  165. Many "object-oriented" programs are written without ever using a true Business Object.
  166. The reason for this is that the issues of maintaining object state are so tricky that
  167. people rarely get around to using Business Objects in their command line programs.
  168. Business Objects come in two types: Business Entity Objects and Business Process Objects.
  169. Business Entity Objects represent things in the business realm: Customer, Store, Employee,
  170. Product, PurchaseOrder. Business Process Objects are those objects that model business
  171. processes.
  172. The following abstractions exist in order to subclass for your business objects.
  173. As you get into using them, you will learn when to use which one, and you will find that
  174. there is of course more than one way to do it.
  175. =over
  176. =item * L<App::RepositoryObject> - An object whose state is shared across multiple sessions as a single row in a database (repository). These are generally the Business Entity Objects.
  177. =item * L<App::SessionObject> - A named object whose state is maintained throughout the session. These are generally the Business Process Objects.
  178. =item * L<App::SessionObject::RepositoryObjectSet> - A named object with session state and shared state consisting of a set of rows from a single table in a database (repository).
  179. =item * L<App::SessionObject::RepositoryObjectDomain> - A named object with session state and shared state consisting of a set of related sets of rows from multiple tables in a database (repository).
  180. =back
  181. The big advantage of writing object-oriented programs is for code reuse.
  182. Whenever someone whips up a perl script to do some processing on the system, that
  183. programming logic is unavailable for use in any other program (such as an interactive
  184. web application).
  185. One way to cure this is to have an L<App::SessionObject> where all of the logic
  186. for a command line program is implemented as a single method call.
  187. The choice of how many SessionObjects to use for all of the logic is a matter of
  188. preference. You could put all this logic on one kitchen-sink-style SessionObject
  189. or you could group the functions into like types and put them on different
  190. SessionObjects. You may wish to have these SessionObject take on the responsibilities
  191. of different "roles" played by members of the organization or tasks performed by
  192. different departments. These can easily be reorganized later. The important
  193. thing is to get the logic out of the command line programs and into objects
  194. so that the logic can be reused later.
  195. When viewed in this light, the command line program only becomes a user interface
  196. for a method call provided by a SessionObject. The easy way to start is just to
  197. pass the %App::options hash (shown below). However, in many cases the program
  198. will do a few more steps to make a more natural call to the SessionObject's method.
  199. =head2 EXAMPLES
  200. vi $PREFIX/etc/app.pl
  201. $conf = {
  202. Repository => {
  203. default => { alias => "db", },
  204. db => {
  205. class => "App::Repository::MySQL",
  206. },
  207. },
  208. SessionObject => {
  209. credit_manager => {
  210. class => "App::SessionObject::CreditManager",
  211. },
  212. },
  213. };
  214. vi $PREFIX/lib/App/SessionObject/CreditManager.pm
  215. use App;
  216. use App::Repository;
  217. package App::SessionObject::CreditManager;
  218. $VERSION = "0.50";
  219. @ISA = ("App::SessionObject");
  220. use strict;
  221. sub check_customer_credit {
  222. my ($self, $options) = @_;
  223. my $customer_id = $options->{customer_id} || die "No customer ID provided";
  224. my $context = $self->{context}; # every Service has a reference to its Context
  225. my $db = $context->repository(); # get the default repository from the Context
  226. # There must be a table named customer with primary key of "customer_id" and
  227. # at least the columns "approval_ind char(1)", "denial_msg varchar(255)",
  228. # "first_name varchar(255)", and "last_name varchar(255)".
  229. my $customer = $db->get_object("customer", $customer_id); # returns an App::RepositoryObject
  230. my ($approval_ind, $denial_msg);
  231. # ... do some processing ...
  232. if ($customer->{first_name} eq "Bill" && $customer->{last_name} eq "Gates") {
  233. $approval_ind = "N";
  234. $denial_msg = "Too rich";
  235. }
  236. else {
  237. $approval_ind = "N";
  238. }
  239. if ($approval_ind eq "Y") {
  240. $customer->set("approval_ind",$approval_ind);
  241. print "Customer $customer_id approved.\n";
  242. }
  243. else {
  244. $customer->set(["approval_ind","denial_msg"],[$approval_ind,$denial_msg]);
  245. print "Customer $customer_id denied: $denial_msg.\n";
  246. }
  247. }
  248. 1;
  249. vi $PREFIX/bin/check_customer_credit
  250. #!/usr/bin/perl -w
  251. # NOTE: All of this code is about the User Interface to the logic.
  252. # The logic itself is hidden away in "App::SessionObject::CreditManager".
  253. use strict;
  254. use App::Options (
  255. options => [qw(dbhost dbname dbuser dbpass customer_id)],
  256. option => {
  257. dbhost => {
  258. description => "database host",
  259. required => 1,
  260. },
  261. dbname => {
  262. description => "database name",
  263. required => 1,
  264. },
  265. dbuser => {
  266. description => "database user",
  267. required => 1,
  268. },
  269. dbpass => {
  270. description => "database password",
  271. required => 1,
  272. },
  273. customer_id => {
  274. description => "the ID of the customer to check",
  275. required => 1,
  276. type => "integer",
  277. },
  278. },
  279. );
  280. use App;
  281. use App::Repository;
  282. {
  283. my $context = $App->context();
  284. my $db = $context->repository();
  285. my $credit_manager = $context->session_object("credit_manager");
  286. $credit_manager->check_customer_credit(\%App::options);
  287. }
  288. =head1 QUICK START TO WEB PROGRAMS
  289. A web program is simply choosing a widget to display on the browser.
  290. Widgets may be arbitrarily complex, containing other widgets, and so taking
  291. the form of an entire web application. Since any widget can be viewed in a
  292. browser, additional widgets may be developed and debugged before they are
  293. integrated into a larger applications.
  294. Widgets (L<App::Widget>) are simply SessionObject's with an html() method
  295. which allows them to be viewed nicely by a web browser. They maintain their
  296. state throughout the duration of the session.
  297. =cut