Advanced Perl Techniques

12,412 views
12,177 views

Published on

The Advanced Perl course that I ran for the UKUUG in Feb 2009.

Published in: Technology
2 Comments
9 Likes
Statistics
Notes
No Downloads
Views
Total views
12,412
On SlideShare
0
From Embeds
0
Number of Embeds
31
Actions
Shares
0
Downloads
549
Comments
2
Likes
9
Embeds 0
No embeds

No notes for slide

Advanced Perl Techniques

  1. 1. Advanced Perl Techniques A One Day Perl Tutorial Dave Cross Magnum Solutions Ltd [email_address]
  2. 2. Advanced Perl Techniques <ul><li>Advanced level training for Perl programmers
  3. 3. Turn intermediate programmers into advanced programmers
  4. 4. “ Modern” Perl
  5. 5. Perl is not dying </li></ul>
  6. 6. Advanced Perl Techniques <ul><li>One day isn't enough time
  7. 7. We'll be moving fairly fast
  8. 8. Lots of pointers to other information
  9. 9. Feel free to ask questions </li></ul>
  10. 10. What We Will Cover <ul><li>What's new in Perl 5.10
  11. 11. Dates and times
  12. 12. Testing </li><ul><li>including coverage analysis </li></ul><li>Database access </li><ul><li>DBIx::Class </li></ul></ul>
  13. 13. What We Will Cover <ul><li>Profiling & Benchmarking
  14. 14. Object oriented programming with Moose
  15. 15. Templates
  16. 16. MVC Frameworks </li><ul><li>Catalyst </li></ul></ul>
  17. 17. Schedule <ul><li>09:45 – Begin
  18. 18. 11:15 – Coffee break
  19. 19. 13:00 – Lunch
  20. 20. 14:00 – Begin
  21. 21. 15:30 – Coffee break
  22. 22. 17:00 – End </li></ul>
  23. 23. Resources <ul><li>Slides available on-line </li><ul><li>http://mag-sol.com/train/public/2009-02/adv </li></ul><li>Also see Slideshare </li><ul><li>http://www.slideshare.net/davorg/slideshows </li></ul><li>Mailing List </li><ul><li>http://lists.mag-sol.com/mailman/listinfo/adv2009 </li></ul><li>Get Satisfaction </li><ul><li>http://getsatisfaction.com/magnum </li></ul></ul>
  24. 24. Perl 5.10
  25. 25. Perl 5.10 <ul><li>Released 18 th Dec 2007 </li><ul><li>Perl's 20 th birthday </li></ul><li>Many new features
  26. 26. Well worth upgrading </li></ul>
  27. 27. New Features <ul><li>Defined-or operator
  28. 28. Switch operator
  29. 29. Smart matching
  30. 30. say()
  31. 31. Lexical $_ </li></ul>
  32. 32. New Features <ul><li>State variables
  33. 33. Stacked file tests
  34. 34. Regex improvements
  35. 35. Many more </li></ul>
  36. 36. Defined Or <ul><li>Boolean expressions “short-circuit”
  37. 37. $val = $val || $default;
  38. 38. $val ||= $default;
  39. 39. What if 0 is a valid value?
  40. 40. Need to check “definedness”
  41. 41. $val = defined $val ? $val : $default;
  42. 42. $val = $default unless defined $val; </li></ul>
  43. 43. Defined Or <ul><li>The defined or operator makes this easier
  44. 44. $val = $val // $default;
  45. 45. A different slant on truth
  46. 46. Checks definedness
  47. 47. Short version too
  48. 48. $val //= $default; </li></ul>
  49. 49. Switch Statement <ul><li>Switch.pm was added with Perl 5.8
  50. 50. Source filter
  51. 51. Parser limitations </li><ul><li>Regular expressions
  52. 52. eval </li></ul><li>5.10 introduces a build-in switch statement </li></ul>
  53. 53. Given ... When <ul><li>Switch is spelled “given”
  54. 54. Case is spelled “when”
  55. 55. Powerful matching syntax </li></ul>
  56. 56. Given Example <ul><li>given ($foo) { when (/^abc/) { $abc = 1; } when (/^def/) { $def = 1; } when (/^xyz/) { $xyz = 1; } default { $nothing = 1; } }
  57. 57. Four new keywords </li><ul><li>given
  58. 58. when
  59. 59. default
  60. 60. continue </li></ul></ul>
  61. 61. given <ul><li>given(EXPR)
  62. 62. Assigns the result of EXPR to $_ within the following block
  63. 63. Similar to do { my $_ = EXPR; ... } </li></ul>
  64. 64. when <ul><li>when (EXPR)
  65. 65. Uses smart matching to compare $_ with EXPR
  66. 66. Equivalent to when ($_ ~~ EXPR)
  67. 67. ~~ is the new smart match operator
  68. 68. Compares two values and “does the right thing” </li></ul>
  69. 69. default <ul><li>default defines a block that is executed if no when blocks match
  70. 70. default block is optional </li></ul>
  71. 71. continue <ul><li>continue keyword falls through to the next when block
  72. 72. Normal behaviour is to break out of given block once the first when condition is matched
  73. 73. given($foo) { when (/x/) {say '$foo contains an x'; continue } when (/y/) { say '$foo contains a y' } default { say '$foo contains no x or y' } } </li></ul>
  74. 74. Smart Matching <ul><li>~~ is the new Smart Match operator
  75. 75. Different kinds of matches
  76. 76. Dependent on the types of the operands
  77. 77. See “perldoc perlsyn” for the full details </li></ul>
  78. 78. Smart Match Examples <ul><li>$foo ~~ $bar; # == or eq
  79. 79. @foo ~~ $bar; # array contains value
  80. 80. %foo ~~ $bar; # hash key exists
  81. 81. $foo ~~ qr{$bar}; # regex match
  82. 82. @foo ~~ @bar; # arrays are identical
  83. 83. %foo ~~ %bar; # hash keys match
  84. 84. Many more alternatives </li></ul>
  85. 85. say() <ul><li>say() is a new alternative to print()
  86. 86. Adds a new line at the end of each call
  87. 87. say($foo); # print $foo, “ ”;
  88. 88. Two characters shorter than print
  89. 89. Less typing </li></ul>
  90. 90. Lexical $_ <ul><li>$_ is a package variable
  91. 91. Always exists in main package
  92. 92. Can lead to subtle bugs when not localised correctly
  93. 93. Can now use my $_ to create a lexically scoped variable called $_ </li></ul>
  94. 94. State Variables <ul><li>Lexical variables disappear when their scope is destroyed
  95. 95. sub variables { my $x; say ++$x; } variables() for 1 .. 3; </li></ul>
  96. 96. State Variables <ul><li>State variables retain their value when their scope is destroyed
  97. 97. sub variables { state $x; say ++$x; } variables() for 1 .. 3;
  98. 98. Like static variables in C </li></ul>
  99. 99. Stacked File Tests <ul><li>People often think you can do this
  100. 100. -f -w -x $file
  101. 101. Previously you couldn't
  102. 102. Now you can
  103. 103. Equivalent to
  104. 104. -x $file && -w _ && -f _ </li></ul>
  105. 105. Regex Improvements <ul><li>Plenty of regular expression improvements
  106. 106. Named capture buffers
  107. 107. Possessive quantifiers
  108. 108. Relative backreferences
  109. 109. New escape sequences
  110. 110. Many more </li></ul>
  111. 111. Named Capture Buffers <ul><li>Variables $1, $2, etc change if the regex is altered
  112. 112. Named captures retain their names
  113. 113. (?<name> ... ) to define
  114. 114. Use new %+ hash to access them </li></ul>
  115. 115. Named Capture Example <ul><li>while (<DATA>) { if (/(?<header>[ws]+) :s+(?<value>.+)/x) { print &quot;$+{header} -> &quot;; print &quot;$+{value} &quot;; } } </li></ul>
  116. 116. Possessive Quantifiers <ul><li>?+ , *+ , ++
  117. 117. Grab as much as they can
  118. 118. Never give it back
  119. 119. Finer control over backtracking
  120. 120. 'aaaa' =~ /a++a/
  121. 121. Never matches </li></ul>
  122. 122. Relative Backreferences <ul><li>g{N}
  123. 123. More powerful version of 1 , 2 , etc
  124. 124. g{1} is the same as 1
  125. 125. g{-1} is the last capture buffer
  126. 126. g{-2} is the one before that </li></ul>
  127. 127. New Escape Sequences <ul><li>h – Horizontal white space
  128. 128. v – Vertical white space
  129. 129. Also H and V </li></ul>
  130. 130. Accessing New Features <ul><li>Some new features would break backwards compatibility
  131. 131. They are therefore turned off by default
  132. 132. Turn them on with the feature pragma
  133. 133. use feature 'say';
  134. 134. use feature 'switch';
  135. 135. use feature 'state';
  136. 136. use feature ':5.10'; </li></ul>
  137. 137. Implicit Loading <ul><li>Two ways to automatically turn on 5.10 features
  138. 138. Require a high enough version of Perl
  139. 139. use 5.10.0; # Or higher
  140. 140. -E command line option
  141. 141. perl -e 'say “hello”'
  142. 142. perl -E 'say “hello”' </li></ul>
  143. 143. Dates and Times
  144. 144. Dates & Times <ul><li>Dozens of date/time modules on CPAN
  145. 145. Date::Manip is almost never what you want
  146. 146. Date::Calc, Date::Parse, Class::Date, Date::Simple, etc
  147. 147. Which one do you choose? </li></ul>
  148. 148. Perl DateTime Project <ul><li>http://datetime.perl.org/
  149. 149. &quot;The DateTime family of modules present a unified way to handle dates and times in Perl&quot;
  150. 150. &quot;unified&quot; is good
  151. 151. Dozens of modules that work together in a consistent fashion </li></ul>
  152. 152. Using DateTime <ul><li>use DateTime; my $dt = DateTime->now; say $dt; # 2009-02-26T11:06:07 say $dt->ymd; # 2009-02-26 say $dt->hms; # 11:08:16 </li></ul>
  153. 153. Using DateTime <ul><li>use DateTime; my $dt = DateTime->new(year => 2009, month => 2, day => 26); say $dt->ymd('/'); # 2009/02/26 say $dt->month; # 2 say $dt->month_name; # February </li></ul>
  154. 154. Arithmetic <ul><li>A DateTime object is a point in time
  155. 155. For date arithmetic you need a duration
  156. 156. Number of years, weeks, days, etc </li></ul>
  157. 157. Arithmetic <ul><li>use DateTime; my $dt = DateTime->new(year => 2009, month => 2, day => 26); my $two_weeks = DateTime::Duration->new(weeks => 2); $dt += $two_weeks; say $dt; # 2009-03-12T00:00:00 </li></ul>
  158. 158. Formatting Output <ul><li>use DateTime; my $dt = DateTime->new(year => 2009, month => 2, day => 26); say $dt->strftime('%A, %d %B %Y'); # Tuesday, 26 February 2009
  159. 159. Control input format with DateTime::Format::Strptime </li></ul>
  160. 160. Parsing & Formatting <ul><li>Ready made parsers and formatters for popular date and time formats
  161. 161. DateTime::Format::HTTP
  162. 162. DateTime::Format::MySQL
  163. 163. DateTime::Format::Excel
  164. 164. DateTime::Format::Baby </li><ul><li>the big hand is on... </li></ul></ul>
  165. 165. Alternative Calendars <ul><li>Handling non-standard calendars
  166. 166. DateTime::Calendar::Julian
  167. 167. DateTime::Calendar::Hebrew
  168. 168. DateTime::Calendar::Mayan
  169. 169. DateTime::Fiction::JRRTolkien::Shire </li></ul>
  170. 170. Calendar Examples <ul><li>use DateTime::Calendar::Mayan; my $dt = DateTime::Calendar::Mayan->now; say $dt->date; # 12.19.16.1.15
  171. 171. use DateTime::Fiction::JRRTolkien::Shire my $dt = DateTime::Fiction::JRRTolkien::Shire->now; say $dt->on_date; # Mersday 24 Solmath 7473 </li></ul>
  172. 172. Testing
  173. 173. Testing <ul><li>Never program without a safety net
  174. 174. Does your code do what it is supposed to do?
  175. 175. Will your code continue to do what it is supposed to do?
  176. 176. Write unit tests
  177. 177. Run those tests all the time </li></ul>
  178. 178. When to Run Tests <ul><li>As often as possible
  179. 179. Before you add a feature
  180. 180. After you have added a feature
  181. 181. Before checking in code
  182. 182. Before releasing code
  183. 183. Constantly, automatically </li></ul>
  184. 184. Testing in Perl <ul><li>Perl makes it easy to write test suites
  185. 185. A lot of work in this area over the last eight years
  186. 186. Test::Simple and Test::More included in Perl distribution
  187. 187. Many more testing modules on CPAN </li></ul>
  188. 188. Simple Test Program <ul><li>use Test::More tests => 4; BEGIN { use_ok('My::Object'); } ok(my $obj = My::Object->new); isa_ok($obj, 'My::Object'); $obj->set_foo('Foo'); is($obj->get_foo, 'Foo'); </li></ul>
  189. 189. Simple Test Output <ul><li>$ prove -v test.t test.... 1..4 ok 1 - use My::Object; ok 2 ok 3 - The object isa My::Object ok 4 ok All tests successful. Files=1, Tests=4, 0 wallclock secs ( 0.02 usr 0.00 sys + 0.05 cusr 0.00 csys = 0.07 CPU) Result: PASS </li></ul>
  190. 190. Adding Test Names <ul><li>use Test::More tests => 4; BEGIN { use_ok('My::Object'); } ok(my $obj = My::Object->new, 'Got an object'); isa_ok($obj, 'My::Object'); $obj->set_foo('Foo'); is($obj->get_foo, 'Foo', 'The foo is &quot;Foo&quot;'); </li></ul>
  191. 191. Output With Names <ul><li>$ prove -v test2.t test2.... 1..4 ok 1 - use My::Object; ok 2 - got an object ok 3 - The object isa My::Object ok 4 - The foo is &quot;Foo&quot; ok All tests successful. Files=1, Tests=4, 0 wallclock secs ( 0.02 usr 0.00 sys + 0.05 cusr 0.00 csys = 0.07 CPU) Result: PASS </li></ul>
  192. 192. Using prove <ul><li>prove is a command line tool for running tests
  193. 193. Runs given tests using Test::Harness
  194. 194. Comes with the Perl distribution
  195. 195. Command line options </li><ul><li>-v verbose output
  196. 196. -r recurse
  197. 197. -s shuffle tests
  198. 198. Many more </li></ul></ul>
  199. 199. Test Anything Protocol <ul><li>Perl tests have been spitting out “ok 1” and not “ok 2” for years
  200. 200. Now this ad-hoc format has a definition and a name
  201. 201. The Test Anything Protocol (TAP)
  202. 202. See Test::Harness::TAP (documentation module) and TAP::Parser </li></ul>
  203. 203. TAP Output <ul><li>More possibilities for test output </li><ul><li>TAP::Harness::Color
  204. 204. Test::TAP::HTMLMatrix </li></ul><li>Make sense of your test results </li></ul>
  205. 205. More Testing Modules <ul><li>Dozens of testing modules on CPAN
  206. 206. Some of my favourites
  207. 207. Test::File
  208. 208. Test::Exception, Test::Warn
  209. 209. Test::Differences
  210. 210. Test::XML (includes Test::XML::XPath) </li></ul>
  211. 211. Writing Test Modules <ul><li>These test modules all work together
  212. 212. Built using Test::Builder
  213. 213. Ensures that test modules all use the same framework
  214. 214. Use it as the basis of your own Test::* modules
  215. 215. Who tests the testers?
  216. 216. Test your Test::Builder test modules with Test::Builder::Tester </li></ul>
  217. 217. Mocking Objects <ul><li>Sometimes it's hard to test external interfaces
  218. 218. Fake them
  219. 219. Test::MockObject pretends to be other objects
  220. 220. Gives you complete control over what they return </li></ul>
  221. 221. Testing Reactors <ul><li>You're writing code that monitors a nuclear reactor
  222. 222. It's important that your code reacts correctly when the reactor overheats
  223. 223. You don't have a reactor in the test environment </li></ul>
  224. 224. Testing Reactors <ul><li>Even if you did, you wouldn't want to make it overheat every time you run the tests
  225. 225. Especially if you're not 100% sure of your code
  226. 226. Or if you're running unattended smoke tests
  227. 227. Fake it with a mock object </li></ul>
  228. 228. My::Monitor Spec <ul><li>If the temperature of a reactor is over 100 then try to cool it down
  229. 229. If you have tried cooling a reactor down 5 times and the temperature is still over 100 then return an error </li></ul>
  230. 230. My::Monitor Code <ul><li>package My::Monitor; sub new { my $class = shift; my $self = { tries => 0 }; return bless $self, $class; } </li></ul>
  231. 231. My::Monitor Code <ul><li>sub check { my $self = shift; my $reactor = shift; my $temp = $reactor->temperature; if ($temp > 100) { $reactor->cooldown; ++$self->{tries}; if ($self->{tries} > 5) { return; } return 1; </li></ul>
  232. 232. My::Monitor Code <ul><li>} else { $self->{tries} = 0; return 1; } } 1; </li></ul>
  233. 233. Mock Reactor <ul><li>Create a mock reactor object that acts exactly how we want it to
  234. 234. Reactor object has two interesting methods
  235. 235. temperature - returns the current temperature
  236. 236. cooldown - cools reactor and returns success or failure </li></ul>
  237. 237. monitor.t <ul><li>use Test::More tests => 10; use Test::MockObject->new; # Standard tests BEGIN { use_ok('My::Monitor'); } ok(my $mon = My::Monitor->new); isa_ok($mon, 'My::Monitor'); </li></ul>
  238. 238. monitor.t <ul><li># Create Mock Reactor Object my $t = 10; my $reactor = Test::MockObject; $reactor->set_bound('temperature', $t); $reactor->set_true('cooldown'); </li></ul>
  239. 239. monitor.t <ul><li># Test reactor ok($mon->check($reactor)); $t = 120; ok($mon->check($reactor)) for 1 .. 5; ok(!$mon->check($reactor)); </li></ul>
  240. 240. How Good Are Your Tests? <ul><li>How much of your code is exercised by your tests?
  241. 241. Devel::Cover can help you to find out
  242. 242. Deep internal magic
  243. 243. Draws pretty charts </li><ul><li>HARNESS_PERL_SWITCHES= -MDevel::Cover make test
  244. 244. cover </li></ul></ul>
  245. 245. Devel::Cover Output
  246. 246. Devel::Cover Output
  247. 247. Devel::Cover Output
  248. 248. Alternative Test Paradigms <ul><li>Not everyone likes the Perl testing framework
  249. 249. Other frameworks are available
  250. 250. Test::Class </li><ul><li>xUnit style framework </li></ul><li>Test::FIT </li><ul><li>Framework for Interactive Testing
  251. 251. http://fit.c2.com </li></ul></ul>
  252. 252. More Information <ul><li>Perl Testing: A Developer's Notebook (Ian Langworth & chromatic)
  253. 253. perldoc Test::Tutorial
  254. 254. perldoc Test::Simple
  255. 255. perldoc Test::More
  256. 256. perldoc Test::Builder
  257. 257. etc... </li></ul>
  258. 258. Benchmarking
  259. 259. Benchmarking <ul><li>Ensure that your program is fast enough
  260. 260. But how fast is fast enough?
  261. 261. premature optimization is the root of all evil </li><ul><li>Donald Knuth
  262. 262. paraphrasing Tony Hoare </li></ul><li>Don't optimise until you know what to optimise </li></ul>
  263. 263. Benchmark.pm <ul><li>Standard Perl module for benchmarking
  264. 264. Simple usage
  265. 265. use Benchmark; my %methods = ( method1 => sub { ... }, method2 => sub { ... }, ); timethese(10_000, methods);
  266. 266. Times 10,000 iterations of each method </li></ul>
  267. 267. Benchmark.pm Output <ul><li>Benchmark: timing 10000 iterations of method1, method2... method1: 6 wallclock secs ( 2.12 usr + 3.47 sys = 5.59 CPU) @ 1788.91/s (n=10000) method2: 3 wallclock secs ( 0.85 usr + 1.70 sys = 2.55 CPU) @ 3921.57/s (n=10000) </li></ul>
  268. 268. Timed Benchmarks <ul><li>Passing timethese a positive number runs each piece of code a certain number of times
  269. 269. Passing timethese a negative number runs each piece of code for a certain number of seconds </li></ul>
  270. 270. Timed Benchmarks <ul><li>use Benchmark; my %methods = ( method1 => sub { ... }, method2 => sub { ... }, ); # Run for 10,000(!) seconds timethese(-10_000, methods); </li></ul>
  271. 271. Comparing Performance <ul><li>Use cmpthese to get a tabular output
  272. 272. Optional export
  273. 273. use Benchmark 'cmpthese'; my %methods = ( method1 => sub { ... }, method2 => sub { ... }, ); cmpthese(10_000, methods); </li></ul>
  274. 274. cmpthese Output <ul><li>Rate method1 method2 method1 2831802/s -- -61% method2 7208959/s 155% --
  275. 275. method2 is 61% slower than method1
  276. 276. Can also pass negative number to cmpthese </li></ul>
  277. 277. Benchmarking is Hard <ul><li>Very easy to produce lots of numbers
  278. 278. Harder to ensure that the numbers are meaningful
  279. 279. Compare code fragments that do the same thing </li></ul>
  280. 280. Bad Benchmarking <ul><li>use Benchmark qw{ timethese }; timethese( 1_000, { Ordinary => sub { my @results = sort { -M $a <=> -M $b } glob &quot;/bin/*&quot;; }, Schwartzian => sub { map $_->[0], sort { $a->[1] <=> $b->[1] } map [$_, -M], glob &quot;/bin/*&quot;; }, }); </li></ul>
  281. 281. What to Benchmark <ul><li>Profile your code
  282. 282. See which parts it is worth working on
  283. 283. Look for code that </li><ul><li>Takes a long time to run, or
  284. 284. Is called many times, or
  285. 285. Both </li></ul></ul>
  286. 286. Devel::DProf <ul><li>Devel::DProf is the standard Perl profiling tool
  287. 287. Included with Perl distribution
  288. 288. Uses Perl debugger hooks
  289. 289. perl -d:DProf your_program
  290. 290. Produces a data file called tmon.out
  291. 291. Command line program dprofpp to view results </li></ul>
  292. 292. Sample Output <ul><li>$ perl -d:DProf ./invoice.pl 244 $ dprofpp Total Elapsed Time = 1.173152 Seconds User+System Time = 0.963152 Seconds Exclusive Times %Time ExclSec CumulS #Calls sec/call Csec/c Name 6.02 0.058 0.067 482 0.0001 0.0001 Params::Validate::_validate 5.09 0.049 0.114 7 0.0070 0.0163 Class::DBI::Loader::mysql::BEGIN 4.15 0.040 0.050 10 0.0040 0.0050 Template::Parser::BEGIN 4.15 0.040 0.166 7 0.0057 0.0237 DateTime::Locale::BEGIN 4.05 0.039 0.094 43 0.0009 0.0022 base::import 3.74 0.036 0.094 449 0.0001 0.0002 DateTime::Locale::_register 3.11 0.030 0.280 4 0.0074 0.0700 DateTime::Format::MySQL::BEGIN 2.91 0.028 0.028 170 0.0002 0.0002 Lingua::EN::Inflect::_PL_noun 2.70 0.026 0.040 1 0.0262 0.0401 Template::Parser::_parse 2.49 0.024 0.024 1113 0.0000 0.0000 Class::Data::Inheritable::__ANON__ 2.08 0.020 0.020 12 0.0017 0.0017 DBD::mysql::db::_login 2.08 0.020 0.020 4 0.0050 0.0050 Template::Stash::BEGIN 2.08 0.020 0.099 9 0.0022 0.0110 Template::Config::load 2.08 0.020 0.067 9 0.0022 0.0074 Template::BEGIN 2.08 0.020 0.039 4 0.0049 0.0097 Lingua::EN::Inflect::Number::BEGIN </li></ul>
  293. 293. Devel::NYTProf <ul><li>New profiling module
  294. 294. Based on work from the New York Times
  295. 295. Enhanced by Tim Bunce
  296. 296. Pretty HTML output </li><ul><li>“borrowed” from Devel::Cover </li></ul><li>Far more flexible
  297. 297. Far more powerful </li></ul>
  298. 298. Using NYTProf <ul><li>Similar to Devel::DProf
  299. 299. $ perl -d:NYTProf ./invoice.pl 244
  300. 300. Writes nytprof.out
  301. 301. $ nytprofhtml
  302. 302. Or
  303. 303. $ nytprofcsv </li></ul>
  304. 304. Conclusions <ul><li>Don't optimise until you know you need to optimise
  305. 305. Don't optimise until you know what to optimise
  306. 306. Use profiling to find out what is worth optimising
  307. 307. Use benchmarking to compare different solutions </li></ul>
  308. 308. More Information <ul><li>perldoc Benchmark
  309. 309. perldoc Devel::DProf
  310. 310. perldoc Devel::NYTProf
  311. 311. Chapters 5 and 6 of Mastering Perl </li></ul>
  312. 312. Object Relational Mapping
  313. 313. ORM <ul><li>Mapping database relations into objects
  314. 314. Tables (relations) map onto classes
  315. 315. Rows (tuples) map onto objects
  316. 316. Columns (attributes) map onto attributes
  317. 317. Don't write SQL </li></ul>
  318. 318. SQL Is Tedious <ul><li>Select the id and name from this table
  319. 319. Select all the details of this row
  320. 320. Select something about related tables
  321. 321. Update this row with these values
  322. 322. Insert a new record with these values
  323. 323. Delete this record </li></ul>
  324. 324. Replacing SQL <ul><li>Instead of
  325. 325. SELECT * FROM my_table WHERE my_id = 10
  326. 326. and then dealing with the prepare/execute/fetch code </li></ul>
  327. 327. Replacing SQL <ul><li>We can write
  328. 328. use My::Object; # warning! not a real orm my $obj = My::Object->retrieve(10)
  329. 329. Or something similar </li></ul>
  330. 330. Writing An ORM Layer <ul><li>Not actually that hard to do yourself
  331. 331. Each class needs an associated table
  332. 332. Each class needs a list of columns
  333. 333. Create simple SQL for basic CRUD operations
  334. 334. Don't do that </li></ul>
  335. 335. Perl ORM Options <ul><li>Plenty of choices on CPAN
  336. 336. Tangram
  337. 337. SPOPS (Simple Perl Object Persistence with Security)
  338. 338. Alzabo
  339. 339. Class::DBI
  340. 340. DBIx::Class </li><ul><li>The current favourite </li></ul></ul>
  341. 341. DBIx::Class <ul><li>Standing on the shoulders of giants
  342. 342. Learning from problems in Class::DBI
  343. 343. More flexible
  344. 344. More powerful </li></ul>
  345. 345. DBIx::Class Example <ul><li>Modeling a CD collection
  346. 346. Three tables
  347. 347. artist (artistid, name)
  348. 348. cd (cdid, artist, title)
  349. 349. track (trackid, cd, title) </li></ul>
  350. 350. Main Schema <ul><li>Define main schema class
  351. 351. DB/Main.pm
  352. 352. package DB::Main; use base qw/DBIx::Class::Schema/; __PACKAGE__->load_classes(); 1; </li></ul>
  353. 353. Object Classes <ul><li>DB/Main/Artist.pm
  354. 354. package DB::Main::Artist; use base qw/DBIx::Class/; __PACKAGE__->load_components(qw/PK::Auto Core/); __PACKAGE__->table('artist'); __PACKAGE__->add_columns(qw/ artistid name /); __PACKAGE__->set_primary_key('artistid'); __PACKAGE__->has_many(cds => 'DB::Main::Cd'); 1; </li></ul>
  355. 355. Object Classes <ul><li>DB/Main/CD.pm
  356. 356. package DB::Main::CD; use base qw/DBIx::Class/; __PACKAGE__->load_components(qw/PK::Auto Core/); __PACKAGE__->table('cd'); __PACKAGE__->add_columns(qw/ cdid artist title year /); __PACKAGE__->set_primary_key('cdid'); __PACKAGE__->belongs_to(artist => 'DB::Main::Artist'); 1; </li></ul>
  357. 357. Inserting Artists <ul><li>my $schema = DB::Main->connect($dbi_str); my @artists = ('The Beta Band', 'Beth Orton'); my $art_rs = $schema->resultset('Artist'); foreach (@artists) { $art_rs->create({ name => $_ }); } </li></ul>
  358. 358. Inserting CDs <ul><li>Hash of Artists and CDs
  359. 359. my %cds = ( 'The Three EPs' => 'The Beta Band', 'Trailer Park' => 'Beth Orton'); </li></ul>
  360. 360. Inserting CDs <ul><li>Find each artist and insert CD
  361. 361. foreach (keys $cds) { my ($artist) = $art_rs->search( { name => $cds{$_} } ); $artist->add_to_cds({ title => $_, }); } </li></ul>
  362. 362. Retrieving Data <ul><li>Get CDs by artist
  363. 363. my ($artist) = $art_rs->search({ name => 'Beth Orton', }); foreach ($artist->cds) { say $_->title; } </li></ul>
  364. 364. Searching for Data <ul><li>Search conditions can be more complex
  365. 365. Alternatives </li><ul><li>$rs->search({year => 2006}, {year => 2007}); </li></ul><li>Like </li><ul><li>$rs->search({name => { 'like', 'Dav%' }}); </li></ul><li>Combinations </li><ul><li>$rs->search({forename => { 'like', 'Dav%' }, surname => 'Cross' }); </li></ul></ul>
  366. 366. Don't Repeat Yourself <ul><li>There's a problem with this approach
  367. 367. Information is repeated
  368. 368. Columns and relationships defined in the database schema
  369. 369. Columns and relationships defined in class definitions </li></ul>
  370. 370. Repeated Information <ul><li>CREATE TABLE artist ( artistid INTEGER PRIMARY KEY, name TEXT NOT NULL ); </li></ul>
  371. 371. Repeated Information <ul><li>package DB::Main::Artist; use base qw/DBIx::Class/; __PACKAGE__-> load_components(qw/PK::Auto Core/); __PACKAGE__->table('artist'); __PACKAGE__-> add_columns(qw/ artistid name /); __PACKAGE__> set_primary_key('artistid'); __PACKAGE__->has_many('cds' => 'DB::Main::Cd'); </li></ul>
  372. 372. Database Metadata <ul><li>Some people don't put enough metadata in their databases
  373. 373. Just tables and columns
  374. 374. No relationships. No constraints
  375. 375. You may as well make each column VARCHAR(255) </li></ul>
  376. 376. Database Metadata <ul><li>Describe your data in your database
  377. 377. It's what your database is for
  378. 378. It's what your database does best </li></ul>
  379. 379. No Metadata (Excuse 1) <ul><li>&quot;This is the only application that will ever access this database&quot;
  380. 380. Bollocks
  381. 381. All data will be shared eventually
  382. 382. People will update your database using other applications
  383. 383. Can you guarantee that someone won't use mysql to update your database? </li></ul>
  384. 384. No Metadata (Excuse 2) <ul><li>&quot;Our database doesn't support those features&quot;
  385. 385. Bollocks
  386. 386. MySQL 3.x is not a database </li><ul><li>It's a set of data files with a vaguely SQL-like query syntax </li></ul><li>MySQL 4.x is a lot better
  387. 387. MySQL 5.x is most of the way there
  388. 388. Don't be constrained by using inferior tools </li></ul>
  389. 389. DBIC::Schema::Loader <ul><li>Creates classes by querying your database metadata
  390. 390. No more repeated data
  391. 391. We are now DRY
  392. 392. Schema definitions in one place
  393. 393. But...
  394. 394. Performance problems </li></ul>
  395. 395. Performance Problems <ul><li>You don't really want to generate all your class definitions each time your program is run
  396. 396. Need to generate the classes in advance
  397. 397. dump_to_dir method
  398. 398. Regenerate classes each time schema changes </li></ul>
  399. 399. Alternative Approach <ul><li>Need one canonical definition of the data tables
  400. 400. Doesn't need to be SQL DDL
  401. 401. Could be in Perl code
  402. 402. Write DBIx::Class definitions
  403. 403. Generate DDL from those
  404. 404. Harder approach </li><ul><li>Might need to generate ALTER TABLE </li></ul></ul>
  405. 405. Conclusions <ul><li>ORM is a bridge between relational objects and program objects
  406. 406. Avoid writing SQL in common cases
  407. 407. DBIx::Class is the currently fashionable module
  408. 408. Lots of plugins
  409. 409. Caveat: ORM may be overkill for simple programs </li></ul>
  410. 410. More Information <ul><li>Manual pages (on CPAN)
  411. 411. DBIx::Class
  412. 412. DBIx::Class::Manual::*
  413. 413. DBIx::Class::Schema::Loader
  414. 414. Mailing list (Google for it) </li></ul>
  415. 415. Moose
  416. 416. Moose <ul><li>A complete modern object system for Perl 5
  417. 417. Based on experiments with Perl 6 object model
  418. 418. Built on top of Class::MOP </li><ul><li>MOP - Meta Object Protocol
  419. 419. Set of abstractions for components of an object system
  420. 420. Classes, Objects, Methods, Attributes </li></ul><li>An example might help </li></ul>
  421. 421. Moose Example <ul><li>package Point; use Moose; has 'x' => (isa => 'Int', is => 'ro'); has 'y' => (isa => 'Int', is => 'rw'); sub clear { my $self = shift; $self->{x} = 0; $self->y(0); } </li></ul>
  422. 422. Understanding Moose <ul><li>There's a lot going on here
  423. 423. use Moose </li><ul><li>Loads Moose environment
  424. 424. Makes our class a subclass of Moose::Object
  425. 425. Turns on strict and warnings </li></ul></ul>
  426. 426. Creating Attributes <ul><li>has 'x' => (isa => 'Int', is => 'ro') </li><ul><li>Creates an attribute called 'x'
  427. 427. Constrainted to be an integer
  428. 428. Read-only accessor </li></ul><li>has 'y' => (isa => 'Int', is => 'rw') </li></ul>
  429. 429. Defining Methods <ul><li>sub clear { my $self = shift; $self->{x} = 0; $self->y(0); }
  430. 430. Standard method syntax
  431. 431. Uses generated method to set y
  432. 432. Direct hash access for x </li></ul>
  433. 433. Subclassing <ul><li>package Point3D; use Moose; extends 'Point'; has 'z' => (isa => 'Int'); after 'clear' => sub { my $self = shift; $self->{z} = 0; }; </li></ul>
  434. 434. Subclasses <ul><li>extends 'Point' </li><ul><li>Similar to use base
  435. 435. Overwrites @ISA instead of appending </li></ul><li>has 'z' => (isa = 'Int') </li><ul><li>Adds new attribute 'z'
  436. 436. No accessor function - private attribute </li></ul></ul>
  437. 437. Extending Methods <ul><li>after 'clear' => sub { my $self = shift; $self->{z} = 0; };
  438. 438. New clear method for subclass
  439. 439. Called after method for superclass
  440. 440. Cleaner than $self->SUPER::clear() </li></ul>
  441. 441. Creating Objects <ul><li>Moose classes are used just like any other Perl class
  442. 442. $point = Point->new(x => 1, y => 2);
  443. 443. $p3d = Point3D->new(x => 1, y => 2, z => 3); </li></ul>
  444. 444. More About Attributes <ul><li>Use the has keyword to define your class's attributes
  445. 445. has 'first_name' => ( is => 'rw' );
  446. 446. Use is to define rw or ro
  447. 447. Omitting is gives an attribute with no accessors </li></ul>
  448. 448. Getting & Setting <ul><li>By default each attribute creates a method of the same name.
  449. 449. Used for both getting and setting the attribute
  450. 450. $dave->first_name('Dave');
  451. 451. say $dave->first_name; </li></ul>
  452. 452. Change Accessor Name <ul><li>Change accessor names using reader and writer
  453. 453. has 'name' => ( is => 'rw', reader => 'get_name', writer => 'set_name', );
  454. 454. See also MooseX::FollowPBP </li></ul>
  455. 455. Required Attributes <ul><li>By default Moose class attributes are optional
  456. 456. Change this with required
  457. 457. has 'name' => ( is => 'ro', required => 1, );
  458. 458. Forces constructor to expect a name
  459. 459. Although that name could be undef </li></ul>
  460. 460. Attribute Defaults <ul><li>Set a default value for an attribute with default
  461. 461. has 'size' => ( is => 'rw', default => 'medium', );
  462. 462. Can use a subroutine reference
  463. 463. has 'size' => ( is => 'rw', default => &rand_size, ); </li></ul>
  464. 464. More Attribute Properties <ul><li>lazy </li><ul><li>Only populate attribute when queried </li></ul><li>trigger </li><ul><li>Subroutine called after the attribute is set </li></ul><li>isa </li><ul><li>Set the type of an attribute </li></ul><li>Many more </li></ul>
  465. 465. More Moose <ul><li>Many more options
  466. 466. Support for concepts like delegation and roles
  467. 467. Powerful plugin support </li><ul><li>MooseX::* </li></ul><li>Lots of work going on in this area </li></ul>
  468. 468. Templating
  469. 469. Templating <ul><li>Many people use templates to produce web pages
  470. 470. Advantages are well known
  471. 471. Standard look and feel (static/dynamic)
  472. 472. Reusable components
  473. 473. Separation of code logic from display logic
  474. 474. Different skill-sets (HTML vs Perl) </li></ul>
  475. 475. Non-Web Templating <ul><li>The same advantages apply to non-web areas
  476. 476. Reports
  477. 477. Business documents
  478. 478. Configuration files
  479. 479. Anywhere you produce output </li></ul>
  480. 480. DIY Templating <ul><li>Must be easy - so many people do it
  481. 481. See perlfaq4
  482. 482. How can I expand variables in text strings? </li></ul>
  483. 483. DIY Templating <ul><li>$text = 'this has a $foo in it and a $bar'; %user_defs = ( foo => 23, bar => 19, ); $text =~ s/$(w+)/$user_defs{$1}/g;
  484. 484. Don't do that </li></ul>
  485. 485. Templating Options <ul><li>Dozens of template modules on CPAN
  486. 486. Text::Template, HTML::Template, Mason, Template Toolkit
  487. 487. Many, many more
  488. 488. Questions to consider </li><ul><li>HTML only?
  489. 489. Template language </li></ul><li>I choose the Template Toolkit </li></ul>
  490. 490. Template Toolkit <ul><li>http://tt2.org/
  491. 491. Very powerful
  492. 492. Both web and non-web
  493. 493. Simple template language
  494. 494. Plugins give access to much of CPAN
  495. 495. Can use Perl code if you want </li><ul><li>But don't do that </li></ul></ul>
  496. 496. Good Book Too!
  497. 497. The Template Equation <ul><li>Data + Template = Output
  498. 498. Data + Alternative Template = Alternative Output
  499. 499. Different views of the same data
  500. 500. Only the template changes </li></ul>
  501. 501. Simple TT Example <ul><li>use Template; use My::Object; my ($id, $format) = @ARGV; $format ||= 'html'; my $obj = My::Object->new($id) or die; my $tt = Template->new; $tt->process(&quot;$format.tt&quot;, { obj => $obj }, &quot;$id.$format&quot;) or die $tt->error; </li></ul>
  502. 502. html.tt <ul><li><html> <head> <title>[% obj.name %]</title> </head> <body> <h1>[% obj.name %]<h1> <p><img src=“[% obj.img %]” /><br /> [% obj.desc %]</p> <ul> [% FOREACH child IN obj.children -%] <li>[% child.name %]</li> [% END %] </body> </html> </li></ul>
  503. 503. text.tt <ul><li>[% obj.name | upper %] Image: [% obj.img %] [% obj.desc %] [% FOREACH child IN obj.children -%] * [% child.name %] [% END %] </li></ul>
  504. 504. Adding New Formats <ul><li>No new code required
  505. 505. Just add new output template
  506. 506. Perl programmer need not be involved </li></ul>
  507. 507. Equation Revisited <ul><li>Data + Template = Output </li><ul><li>Template Toolkit </li></ul><li>Template + Output = Data </li><ul><li>Template::Extract </li></ul><li>Data + Output = Template </li><ul><li>Template::Generate </li></ul></ul>
  508. 508. Catalyst
  509. 509. MVC Frameworks <ul><li>MVC frameworks are a popular way to write applications </li><ul><li>Particularly web applications </li></ul><li>Model </li><ul><li>Data storage & data access </li></ul><li>View </li><ul><li>Data presentation layer </li></ul><li>Controller </li><ul><li>Business logic to glue it all together </li></ul></ul>
  510. 510. MVC Examples <ul><li>Ruby on Rails
  511. 511. Django (Python)
  512. 512. Struts (Java)
  513. 513. CakePHP
  514. 514. Many examples in most languages
  515. 515. Perl has many options </li></ul>
  516. 516. MVC in Perl <ul><li>Maypole </li><ul><li>The original Perl MVC framework </li></ul><li>CGI::Application </li><ul><li>Simple MVC for CGI programming </li></ul><li>Jifty </li><ul><li>Developed and used by Best Practical </li></ul><li>Catalyst </li><ul><li>Currently the popular choice </li></ul></ul>
  517. 517. Catalyst <ul><li>MVC framework in Perl
  518. 518. Building on other heavily-used tools
  519. 519. Model uses DBIx::Class
  520. 520. View uses Template Toolkit
  521. 521. These are just defaults
  522. 522. Can use anything you want </li></ul>
  523. 523. Simple Catalyst App <ul><li>Assume we already have model </li><ul><li>CD database from DBIx::Class section </li></ul><li>Use catalyst.pl to create project
  524. 524. $ catalyst.pl CD created &quot;CD&quot; created &quot;CD/script&quot; created &quot;CD/lib&quot; created &quot;CD/root&quot; ... many more ... </li></ul>
  525. 525. What Just Happened? <ul><li>Catalyst just generated a lot of useful stuff for us
  526. 526. Test web servers </li><ul><li>Standalone and FastCGI </li></ul><li>Configuration files
  527. 527. Test stubs
  528. 528. Helpers for creating models, views and controllers </li></ul>
  529. 529. A Working Application <ul><li>We already have a working application
  530. 530. $ CD/script/cd_server.pl ... lots of output [info] CD powered by Catalyst 5.7015 You can connect to your server at http://localhost:3000
  531. 531. Of course, it doesn't do much yet </li></ul>
  532. 532. Simple Catalyst App
  533. 533. Next Steps <ul><li>Use various helper programs to create models and views for your application
  534. 534. Write controller code to tie it all together
  535. 535. Many plugins to handle various parts of the process </li><ul><li>Authentication
  536. 536. URL resolution
  537. 537. Session handling
  538. 538. etc... </li></ul></ul>
  539. 539. Create a View <ul><li>$ script/cd_create.pl view Default TT exists &quot;/home/dave/training/cdlib/CD/script/../lib/CD/View&quot; exists &quot;/home/dave/training/cdlib/CD/script/../t&quot; created &quot;/home/dave/training/cdlib/CD/script/../lib/CD/View/Default.pm&quot; created &quot;/home/dave/training/cdlib/CD/script/../t/view_Default.t&quot; </li></ul>
  540. 540. Remove Default Message <ul><li>In lib/CD/Controller/Root.pm
  541. 541. sub index :Path :Args(0) { my ( $self, $c ) = @_; # Hello World $c->response_body($c->welcome_message); }
  542. 542. Remove response_body line
  543. 543. Default behaviour is to render index.tt
  544. 544. Need to create that </li></ul>
  545. 545. index.tt <ul><li>root/index.tt
  546. 546. <html> <head> <title>CDs</title> </head> <body> <ul> [% FOREACH cd IN [ 1 .. 10 ] %] <li>CD [% cd %]</li> [% END %] </ul> </body> </html> </li></ul>
  547. 547. New Front Page
  548. 548. Adding Data <ul><li>Of course that's hard-coded data
  549. 549. Need to add a model class
  550. 550. And then more views
  551. 551. And some controllers
  552. 552. There's a lot to do
  553. 553. I recommend working through a tutorial </li></ul>
  554. 554. Easier Catalyst <ul><li>A lot of web applications do similar things
  555. 555. Given a database
  556. 556. Produce screens to edit the data
  557. 557. Surely most of this can be automated
  558. 558. It's called CatalystX::ListFramework::Builder
  559. 559. (Demo) </li></ul>
  560. 560. CatX::LFBuilder <ul><li>Does a lot of work
  561. 561. On the fly
  562. 562. For every request
  563. 563. No security on table updates
  564. 564. So it's not right for every project
  565. 565. Very impressive though </li></ul>
  566. 566. Conclusions <ul><li>There's a lot to bear in mind when writing a web app
  567. 567. Using the right framework can help
  568. 568. Catalyst is the most popular Perl framework
  569. 569. As powerful as any other framework </li><ul><li>In any language </li></ul><li>Lots of work still going on
  570. 570. Large team, active development </li></ul>
  571. 571. Further Information
  572. 572. Further Information <ul><li>Some suggestions for places to go for further information
  573. 573. Web sites
  574. 574. Books
  575. 575. Magazines
  576. 576. Mailing lists
  577. 577. Conferences </li></ul>
  578. 578. London Perl Mongers <ul><li>http://london.pm.org/
  579. 579. Mailing list
  580. 580. Regular meetings </li><ul><li>Both social and technical </li></ul><li>London Perl Workshop
  581. 581. Many other local Perl Monger groups </li><ul><li>http://pm.org/ </li></ul></ul>
  582. 582. Web Sites <ul><li>use Perl; </li><ul><li>Perl news site
  583. 583. Also journals </li></ul><li>perl.com </li><ul><li>O'Reilly run site
  584. 584. High quality articles </li></ul></ul>
  585. 585. Web Sites <ul><li>Perl Monks </li><ul><li>Best web site for Perl questions
  586. 586. Many Perl experts </li></ul><li>The Perl directory </li><ul><li>http://perl.org/
  587. 587. Lists of many Perl-related sites </li></ul></ul>
  588. 588. Books <ul><li>Some recent Perl books
  589. 589. Perl Best Practices - Damian Conway
  590. 590. Advanced Perl Programming - Simon Cozens
  591. 591. Perl Hacks - chromatic, Conway & Poe
  592. 592. Intermediate Perl - Schwartz, foy & Phoenix
  593. 593. Mastering Perl - brian d foy </li></ul>
  594. 594. More Books <ul><li>Higher Order Perl - Mark-Jason Dominus
  595. 595. Minimal Perl - Tim Maher
  596. 596. Pro Perl Debugging - Richard Foley & Joe McMahon
  597. 597. Perl & LWP - Sean M Burke </li><ul><li>Updated online edition
  598. 598. http://lwp.interglacial.com/ </li></ul><li>See http://books.perl.org/ </li></ul>
  599. 599. Magazines <ul><li>The Perl Review </li><ul><li>http://www.theperlreview.com/ </li></ul><li>Randal's monthly columns </li><ul><li>Linux Magazine
  600. 600. SysAdmin </li></ul></ul>
  601. 601. Mailing Lists <ul><li>Many mailing lists devoted to Perl topics
  602. 602. See http://lists.cpan.org/ </li></ul>
  603. 603. Conferences <ul><li>The Open Source Convention </li><ul><li>San Diego 20-24 July 2009 </li></ul><li>YAPC </li><ul><li>Pittsburgh 22-24 June 2009
  604. 604. Lisbon 3-5 August 2009
  605. 605. Brazil, Asia, Israel, Australia </li></ul><li>One-Day Perl Workshops
  606. 606. See http://yapc.org/ </li></ul>
  607. 607. <ul>That's all folks </ul><ul><li>Any questions? </li></ul>

×