Everything but the
   Secret Sauce Contains
                                       No Jifty!
Modules, Magic and Monstrosit...
Jesse Vincent
   Best Practical
We make Hiveminder


    Hiveminder
It’s not opensource
We built lots of cool
      stuff for Hiveminder

Hiveminder
We opensource
everything we can
Today’s Agenda
Ten tools and techniques to help you:
Find bugs faster
Build web apps
Ship software
Get input from users
Ow...
Find bugs faster
TAP-Harness-Remote
    Run your tests over there.
The Problem
Hiveminder has
   lots of tests


Hiverminder
That's a problem?
Yes.
30 minutes to run
tests on my Macbook


    Macbook   30
(It took the same on
   a Macbook Pro)


    (Macbook Pro   )
What to do?
TAP::Harness 3.0
I have two cores!


          2   !
TAP::Harness::Parallel
prove -j 5 --fork
22 minutes


prove -j 5 22
Better!


     !
Not good.
Run tests on a server!


                     !
rsync -rvp . server:
ssh server quot;prove -j 9 tquot;
Better.
Annoying to run.
TAP::Harness::Remote
Magic Remote Testing
# ~/.remote_test
    ---
    local: /path/to/local/testing/root/
    host:
           - remote1.testing.host.example.com
 ...
prove --harness TAP::Harness::Remote t/*.t
16.5 minutes


    16.5   !
prove --harness TAP::Harness::Remote -j 5 t/*.t
Magic Parallel
Remote Testing
12 minutes!


    12   !
Not good enough
    for TDD
What I need is...

•   Fast Servers (           )
•   Lots of Fast Servers (           )
•   Right Now (                  ...
A use for cloud
  computing!


                  !
TAP::Harness::Remote::EC2
4 hosts. -j 5
89 seconds


    89
Yatta!
Yatta!
EC2 Caveats
Default Perl builds are really bad
               Perl
Machines are mostly underpowered

(“XL” instances are g...
What's next for
::Harness::Remote::* ?
More polish on EC2 tools
EC2
Better EC2 instance control
EC2
More widespread usage
Carp::REPL
It's not quite a debugger
How many of you use
 the Perl debugger?


Perl
How many of you
know how to use the
   perl debugger?
I don’t, either.
So, what do I use?
31b:~ jesse$ perl /tmp/contrived.pl
Undefined subroutine &main::does_not_exist called
at /tmp/contrived.pl line 20.

31b:~...
31b:~ jesse$ perl /tmp/contrived.pl
Undefined subroutine &main::does_not_exist called
at /tmp/contrived.pl line 22.

31b:~...
Ick. A Print Statement.


         Print
Anyone else here use
   print statement
     debugging?

 print
(Oh god, I hope I'm
    not alone)
Acme, you wrote
           Devel::ebug...


Leon Brocard Devel::ebug    …
Do you use it?
I want a simple
debugger that's easier
than print statements

    print
sartak created
        Carp::REPL


Shawn Moore Carp::REPL
A lightweight, modern,
 interactive debugger
Built on Devel::REPL


 Devel::REPL
Carp::REPL Hooks into
   $SIG{__DIE__}


Carp::REPL   $SIG{__DIE__}
$SIG{__WARN__}
hooks are optional


$SIG{__WARN__}
31b:~ jesse$ perl -MCarp::REPL /tmp/contrived.pl
Undefined subroutine &main::does_not_exist called
at /tmp/contrived.pl li...
That's not a shell
    prompt
31b:~ jesse$ perl -MCarp::REPL /tmp/contrived.pl
Undefined subroutine &main::does_not_exist called
at /tmp/contrived.pl li...
It's Perl, but
       it's not just Perl


Perl                 Perl
:t   -   Stack trace
:u   -   Up one stack frame
:d   -   Down one stack frame
:e   -   Print this frame's lexical environ...
$ :t
0: Carp::REPL::repl called at /tmp/contrived.pl:22.
   1: main::c called at /tmp/contrived.pl:15.
   2: main::b calle...
$ :e
$Env = { quot;$to_callquot; => do { my $v = 'does_not_exist' } };
$ :u
$ :u
Now at /tmp/contrived.pl:9 (frame 2).
$ :...
Why is my code 'warn'ing?
 Maybe it's in an eval.
 eval
 Or in a CPAN library.
 CPAN
 No problem!

 perl -MCarp::REPL=warn
31b:~ jesse$ perl -MCarp::REPL=warn /tmp/contrived.pl
Use of uninitialized value in concatenation (.) or string at /tmp/co...
Inserting breakpoints
You know your 'print' statements?
  print
Turn them into breakpoints.

Two ways:
2                  ...
18.sub   c {
19.      my $to_call = shift;
20.      no strict 'refs';
21.      Carp::REPL::repl(); #Gimme a breakpoint her...
What's next for
       Carp::REPL?
I have no idea.

It's simple.

It works.
Build web apps
Template::Declare
  A Pure Perl Templating Engine
                                    2007 Talk
                          ...
Perl has two big
       templating camps


Perl               2
Template::Toolkit
A DSL for templates
                  DSL
It's NOT Perl

Why should I learn a new language for
templates?
HTML::Mason


There's Perl inside.
         Perl
HTML::Mason

              <mason><is><still>
                  <full><of>
              <angle><brackets>


<   ><   ><  ...
HTML::Mason

            </brackets></angle>
                </of></full>
            </still></is></mason>


</   ></    ...
I'm Just A Simple
   Perl Hacker


      Perl
I needed something
    more Perlish


    Perl
template '/pages/mypage.html' => sub {
    html {
        head {};
        body {
            h1 {'Hey, this is text'};
  ...
template choices => page {
    h1 { 'My Choices' }
    dl {
        my $choices = Doxory::Model::ChoiceCollection->new;
  ...
But!
Content! Templates!
           !                  !
Design! Code!
         !            !
OMGWTFBBQ!?
           !?
T...
The person who told
 you it's wrong was
   lying to you.
We're Perl hackers


     Perl
Why are we writing
 our templates in
another language?
This is not 1997


 1997
It’s 2008

 2008
People use CSS
for design now


     CSS
Programmers still have
  to make templates
Templates run like
    CODE
Because they ARE code
Let's use our CODING
  tools to work with
          them
How about
Refactoring?
Have you ever tried to
    refactor HTML?


HTML
template 'mypage.html' => page {
 h1 { 'Two choices' };
 div { attr { class => 'item' };
       h2 { 'Item 1'};
   };
 div...
template 'mypage.html' => page {
 h1 { 'Two choices' };
 for (quot;Item 1quot;, quot;Item 2quot;) { item($_); }
};

sub it...
We can refactor
  templates!


             !
Our HTML is
magically valid


HTML
(Syntax errors are...
   Syntax Errors)


                        …
Object Oriented
  Templates
Subclassing

It just works

We're using Perl's symbol table
Perl
(Template::Declare's show() passes the class for you)
Tem...
Mixins

alias Some::Template::Library under '/path';

That's it.
Closures
Tags as Closures
HTML tags take blocks of content
HTML
Our tag methods take blocks of Perl
                         Perl
T...
sub h1 (&;$) {
  my $code = shift;

    ...

    if (defined wantarray) {
      return sub { ...closure around $code...};
...
What's next for
     Template::Declare?
HTML Attribute Validation
HTML

Compile to .js
js
CSS::Squish
A compiler for Cascading Style Sheets




        CSS
The Problem

Many small CSS Files
CSS
 Easy to work with

 Painful to serve
The Problem

One big CSS file
                        CSS
 Painful to work with

 Easy to serve
How CSS works
main.css:
@import quot;yui-fonts.cssquot;;
@import quot;base.cssquot;;
@import quot;layout.cssquot;;
@import...
How CSS works
• Browser downloads CSS stylesheets listed
  in HTML
• Browser processes each stylesheet for
  @include dire...
How CSS works
To make CSS faster, you can tell browsers to cache stylesheets
                                             ...
How CSS::Squish works
 It pretends to be a browser.

 You give it the path to a stylesheet.

 It returns the fully compute...
How we use
         CSS::Squish
Instead of:
 <link rel=quot;stylesheetquot; type=quot;text/cssquot;
href=quot;main.css”/>
...
How we use
                CSS::Squish
 If we have a cached copy of the squished CSS, name the ‘file’ as an
MD5 of the cont...
What’s next for
         CSS::Squish
 Refactor the MD5 hash bits from Jifty to
CSS::Squish
 MD5                    Jifty
C...
Ship software
App::ChangeLogger
    Gorgeous changelogs
We create a lot of
    software
(145 Projects in
 bps-public svn)


                   145
We’re not so good at
   doing releases
Lots of manual work
ShipIt can help with
     most of it


ShipIt
What about
Changelog?
svn log svn://svn.foo.com/MyProj
> Changelog
Ship it!


  ShipIt
Ew. No. Ick.
Wrong. Bad.
App::ChangeLogger
Two commands


• sort-changelog
• generate-changelog

                       2
Ok, three commands:

• svn log --xml svn://svn.bestpractical.com/
  App-Changelogger > changelog.raw.xml
• ./bin/sort-chan...
What's next for
    App::Changelogger?
Use it on itself. (Release it)

Store changelog metadata in repository

Support for...
Shipwright
  Build. Ship.
The Problem



CPAN
The Problem


Everything that
 is not CPAN
    : CPAN
We make RT


   RT
RT has Many
Dependencies


  RT
Apache::DBI                  Digest::MD5               HTML::Scrubber                Mail::Mailer                 Test::Wa...
That’s just the non-core
 CPAN dependencies.
   Without all their
     dependencies.
116 CPAN distributions
   once you do the
      recursion

             116
And then there are the
 external libraries and
      programs
• perl        • readline
• expat       • zlib
• fontconfig   • gnupg
• freetype    • mysql
• libgd       • postgresql
• lib...
Plagger beats RT.
(It has 135 CPAN deps)


Plagger    (Plagger   135   )
RT is hard to install


   RT
RT should be easy to
       install
All software should be
     easy to install
What Shipwright does

Tracks all dependencies in version control

  (As far down as you want. I skip libc.)
              ...
What Shipwright does

Computes a full dependency order

No more recursive CPAN installs
        CPAN



        Shipwright
What Shipwright does

Keeps all packages in version control

No more “that site is down”




          Shipwright
What Shipwright does

 Automates multi-package builds

  (No manual intervention)




     Shipwright
What Shipwright does

Makes installed packages relocatable

(Wraps all scripts and binaries)




          Shipwright
What Shipwright does

Makes historical builds reproducible

(No more “Oh. that API changed in 2.0”)
          API 2.0




...
Shipwright and CPAN
CPAN-friendly CPAN
  (Not CPAN-only) CPAN
CPAN dist import CPAN
Automatic CPAN dependency resolution

...
Shipwright and C

 Native support for autoconfiscated packages

 No support for magic C->C dependency
resolutions
  C      ...
Shipwright and Ruby

Not Ruby friendly :(
    Ruby
No Gem support yet
Gem
Hackathon this weekend?



                 Ship...
What you can ship

A platform-neutral source distribution



Platform-specific binary distributions
Making a Shipwright
            Vessel
svnadmin create file:///Users/jesse/shiprepo
shipwright create --repository
     sv...
Building a Shipwright
            Vessel
svn co file:///Users/jesse/shiprepo/myproject
cd myproject
./bin/shipwright-build...
Using a Shipwright
            Vessel

•   tar xzvf myproject.tgz c /usr/local/
    myproject

•   ln -s /usr/local/myproj...
What's next for
      Shipwright?

Build tool usability improvements

Ruby support?
Ruby
Get input from users
Date::Extract
    Get a date
The Problem
Pick up the drycleaning
on tuesday after school
There are many Date /
Time parsers on CPAN


CPAN
Date::Manip
Time::ParseDate
Date::Parse
DateTime::Format::Natural
Each can parse dates
     and times
None of them are any
good at finding dates in
   a block of text
Timezones are hard
Most parsers generate
 many false positives
use Date::Extract;

my $arbitrary_text = <<EOF;
I need to plan for my trip. On Sunday
afternoon, I'll head on to taiwan.
E...
It's simple.
It's unsexy.
It's reliable.
What's next for
         Date::Extract?

Parsing more obscure human-written dates?


Date::Extract::Lingua::* ?
The Feedback Box
Let users make suggestions everywhere
mailto: links?
getsatisfaction.com?
I give up.
Don't let your users
      give up.
Feedback is important!
Feedback can be easy!
If you make it easy for
    users to give you
       feedback...
You can capture lots of
  good information!
From: Jesse Vincent / Feedback <comment-373709-destygrypuju@tasks.hiveminder.com>
Date: Mon, 12 May 2008 12:31:49 -0700
Su...
Collect lots of feedback
Reply to lots of
   feedback
Conversations make
   users happy
Happy = Loyal
Own the inbox
Net::IMAP::Server
  An IMAP Server in Pure Perl




  Pure Perl IMAP Server
Why?
Offline Access
iPhone Access


  iPhone
Desktop Access
Really, we just like
  things that are
 sick and wrong.
Now Hiveminder users
 can take their tasks
      with them

Hiveminder
Magic mailboxes
Update your tasks
  while offline
What sort of mailbox
do you use with that?
mbox?
no
maildir?
no
How about Perl?


   Perl
Net::IMAP::Server
Complete RFC 3501
  Implementation


   RFC 3501
Write your own
  backends
Let’s write one now
How about a
Spam server?


Spam
package Demo::IMAP::Auth;
use base 'Net::IMAP::Server::DefaultAuth';

sub auth_plain {
    my ($self, $user, $pass ) = @_;...
package Demo::IMAP::Model;
use base 'Net::IMAP::Server::DefaultModel';

sub init {
    my $self = shift;
    $self->root(D...
package Demo::IMAP::Mailbox;
use base qw/Net::IMAP::Server::Mailbox/;

my $msg = Net::IMAP::Server::Message->new(<<'EOM');...
#!/usr/bin/perl

use Net::IMAP::Server;
Net::IMAP::Server->new(
        auth_class => quot;Demo::IMAP::Authquot;,
        ...
It runs! Ship it!
(Just add SSL certificates)


                 SSL
with.hm
Assign tasks by email
We wanted to make it
 easy to work with
Hiveminder by email.

Hiveminder
We had a few ideas...


                   …
Cc:
Too clumsy
Bcc:
Too likely to break
Commands in the body
Too ugly
hm...
What could we do?
DNS Hacks!
Everybody loves DNS hacks




     DNS
.hm
Hiveminder!
.hm
Heard and McDonald
      Islands!
with.hm
Send your email with
    Hiveminder


       Hiveminder
Wildcard MX Record!


          MX   !
*.with.hm ➡
mail.hiveminder.com
An Example:

From: jesse@bestpractical.com
To: miyagawa@bulknews.net.with.hm
Subject: Could you release a new version of p...
My mail server looks up
 bulknews.net.with.hm


        bulknews.net.with.hm
“Oh. That's handled by
 mail.hiveminder.com”


       mail.hiveminder.com
mail.hiveminder.com
  unwraps the address.


mail.hiveminder.com
Hiveminder creates a task
for miyagawa@bulknews.net


miyagawa@bulknews.net
Hiveminder emails
miyagawa@bulknews.net


  miyagawa@bulknews.net
Preventing Spam
miyagawa@bulknews.net.my-
      secret.with.hm


            .
I bet you can come up
with even scarier uses
   of wildcard DNS.

    DNS
Thank you!
Hiveminder - Everything but the Secret Sauce
Hiveminder - Everything but the Secret Sauce
Hiveminder - Everything but the Secret Sauce
Hiveminder - Everything but the Secret Sauce
Hiveminder - Everything but the Secret Sauce
Hiveminder - Everything but the Secret Sauce
Hiveminder - Everything but the Secret Sauce
Hiveminder - Everything but the Secret Sauce
Hiveminder - Everything but the Secret Sauce
Hiveminder - Everything but the Secret Sauce
Hiveminder - Everything but the Secret Sauce
Hiveminder - Everything but the Secret Sauce
Hiveminder - Everything but the Secret Sauce
Upcoming SlideShare
Loading in...5
×

Hiveminder - Everything but the Secret Sauce

6,662

Published on

Ten tools and techniques to help you:
Find bugs faster バグの検出をもっと素早く
Build web apps ウェブアプリの構築
Ship software ソフトのリリース
Get input from users ユーザからの入力を受けつける
Own the Inbox 受信箱を用意する
今日の話

Published in: Technology
0 Comments
1 Like
Statistics
Notes
  • Be the first to comment

No Downloads
Views
Total Views
6,662
On Slideshare
0
From Embeds
0
Number of Embeds
1
Actions
Shares
0
Downloads
37
Comments
0
Likes
1
Embeds 0
No embeds

No notes for slide

Transcript of "Hiveminder - Everything but the Secret Sauce"

  1. 1. Everything but the Secret Sauce Contains No Jifty! Modules, Magic and Monstrosities created for
  2. 2. Jesse Vincent Best Practical
  3. 3. We make Hiveminder Hiveminder
  4. 4. It’s not opensource
  5. 5. We built lots of cool stuff for Hiveminder Hiveminder
  6. 6. We opensource everything we can
  7. 7. Today’s Agenda Ten tools and techniques to help you: Find bugs faster Build web apps Ship software Get input from users Own the Inbox
  8. 8. Find bugs faster
  9. 9. TAP-Harness-Remote Run your tests over there.
  10. 10. The Problem
  11. 11. Hiveminder has lots of tests Hiverminder
  12. 12. That's a problem?
  13. 13. Yes.
  14. 14. 30 minutes to run tests on my Macbook Macbook 30
  15. 15. (It took the same on a Macbook Pro) (Macbook Pro )
  16. 16. What to do?
  17. 17. TAP::Harness 3.0
  18. 18. I have two cores! 2 !
  19. 19. TAP::Harness::Parallel
  20. 20. prove -j 5 --fork
  21. 21. 22 minutes prove -j 5 22
  22. 22. Better! !
  23. 23. Not good.
  24. 24. Run tests on a server! !
  25. 25. rsync -rvp . server: ssh server quot;prove -j 9 tquot;
  26. 26. Better.
  27. 27. Annoying to run.
  28. 28. TAP::Harness::Remote
  29. 29. Magic Remote Testing
  30. 30. # ~/.remote_test --- local: /path/to/local/testing/root/ host: - remote1.testing.host.example.com - remote2.testing.host.example.com root: /where/to/place/local/root/on/remote/ user: username master: 1 perl: /usr/bin/perl ssh: /usr/bin/ssh ssh_args: - -x - -S - '~/.ssh/master-%r@%h:%p'
  31. 31. prove --harness TAP::Harness::Remote t/*.t
  32. 32. 16.5 minutes 16.5 !
  33. 33. prove --harness TAP::Harness::Remote -j 5 t/*.t
  34. 34. Magic Parallel Remote Testing
  35. 35. 12 minutes! 12 !
  36. 36. Not good enough for TDD
  37. 37. What I need is... • Fast Servers ( ) • Lots of Fast Servers ( ) • Right Now ( ) • Not Very Often ( )
  38. 38. A use for cloud computing! !
  39. 39. TAP::Harness::Remote::EC2
  40. 40. 4 hosts. -j 5
  41. 41. 89 seconds 89
  42. 42. Yatta!
  43. 43. Yatta!
  44. 44. EC2 Caveats Default Perl builds are really bad Perl Machines are mostly underpowered (“XL” instances are great, though) XL Machine Setup/Teardown is ~manual EC2
  45. 45. What's next for ::Harness::Remote::* ? More polish on EC2 tools EC2 Better EC2 instance control EC2 More widespread usage
  46. 46. Carp::REPL It's not quite a debugger
  47. 47. How many of you use the Perl debugger? Perl
  48. 48. How many of you know how to use the perl debugger?
  49. 49. I don’t, either.
  50. 50. So, what do I use?
  51. 51. 31b:~ jesse$ perl /tmp/contrived.pl Undefined subroutine &main::does_not_exist called at /tmp/contrived.pl line 20. 31b:~ jesse$ vim /tmp/contrived.pl 18.sub c { 19. my $to_call = shift; 20. $to_call = quot;does_quot;.$to_call; 21. no strict refs; 22. $to_call->(); 23.}
  52. 52. 31b:~ jesse$ perl /tmp/contrived.pl Undefined subroutine &main::does_not_exist called at /tmp/contrived.pl line 22. 31b:~ jesse$ vim /tmp/contrived.pl 18.sub c { 19. my $to_call = shift; 20. $to_call = quot;does_quot;.$to_call; 21. no strict refs; 22. use Carp; Carp::cluck(quot;$to_callquot;); 23. $to_call->(); 24.}
  53. 53. Ick. A Print Statement. Print
  54. 54. Anyone else here use print statement debugging? print
  55. 55. (Oh god, I hope I'm not alone)
  56. 56. Acme, you wrote Devel::ebug... Leon Brocard Devel::ebug …
  57. 57. Do you use it?
  58. 58. I want a simple debugger that's easier than print statements print
  59. 59. sartak created Carp::REPL Shawn Moore Carp::REPL
  60. 60. A lightweight, modern, interactive debugger
  61. 61. Built on Devel::REPL Devel::REPL
  62. 62. Carp::REPL Hooks into $SIG{__DIE__} Carp::REPL $SIG{__DIE__}
  63. 63. $SIG{__WARN__} hooks are optional $SIG{__WARN__}
  64. 64. 31b:~ jesse$ perl -MCarp::REPL /tmp/contrived.pl Undefined subroutine &main::does_not_exist called at /tmp/contrived.pl line 22. 0: Carp::REPL::repl called at /tmp/contrived.pl:22. 1: main::c called at /tmp/contrived.pl:15. 2: main::b called at /tmp/contrived.pl:9. 3: main::a called at /tmp/contrived.pl:27. Now at /tmp/contrived.pl:22 (frame 0). $
  65. 65. That's not a shell prompt
  66. 66. 31b:~ jesse$ perl -MCarp::REPL /tmp/contrived.pl Undefined subroutine &main::does_not_exist called at /tmp/contrived.pl line 22. 0: Carp::REPL::repl called at /tmp/contrived.pl:22. 1: main::c called at /tmp/contrived.pl:15. 2: main::b called at /tmp/contrived.pl:9. 3: main::a called at /tmp/contrived.pl:27. Now at /tmp/contrived.pl:22 (frame 0). $ warn $0 /tmp/contrived.pl at (eval 135) line 15, <FIN> line 1.
  67. 67. It's Perl, but it's not just Perl Perl Perl
  68. 68. :t - Stack trace :u - Up one stack frame :d - Down one stack frame :e - Print this frame's lexical environment :q - Quit this REPL $_e - ARRAYREF of this frame's @_
  69. 69. $ :t 0: Carp::REPL::repl called at /tmp/contrived.pl:22. 1: main::c called at /tmp/contrived.pl:15. 2: main::b called at /tmp/contrived.pl:9. 3: main::a called at /tmp/contrived.pl:27. $
  70. 70. $ :e $Env = { quot;$to_callquot; => do { my $v = 'does_not_exist' } }; $ :u $ :u Now at /tmp/contrived.pl:9 (frame 2). $ :e $Env = { quot;$to_callquot; => do { my $v = 'exist' } }; $ :u Now at /tmp/contrived.pl:27 (frame 3). $ :e $Env = { quot;$to_callquot; => do { my $v = '' } }; $ :d Now at /tmp/contrived.pl:9 (frame 2). $ :e $Env = { quot;$to_callquot; => do { my $v = 'exist' } }; $ warn join(quot;, quot;,@$_a); exist at (eval 138) line 18, <FIN> line 4.
  71. 71. Why is my code 'warn'ing? Maybe it's in an eval. eval Or in a CPAN library. CPAN No problem! perl -MCarp::REPL=warn
  72. 72. 31b:~ jesse$ perl -MCarp::REPL=warn /tmp/contrived.pl Use of uninitialized value in concatenation (.) or string at /tmp/contrived.pl line 8. 0: Carp::REPL::repl called at /tmp/contrived.pl:8. 1: main::a called at /tmp/contrived.pl:27. Now at /tmp/contrived.pl:8 (frame 0). $ :e $Env = { quot;$to_callquot; => do { my $v = undef } }; $ :q Undefined subroutine &main::does_not_exist called at /tmp/contrived.pl line 22, <FIN> line 2. 0: Carp::REPL::repl called at /tmp/contrived.pl:22. 1: main::c called at /tmp/contrived.pl:15. 2: main::b called at /tmp/contrived.pl:9. 3: main::a called at /tmp/contrived.pl:27. Now at /tmp/contrived.pl:22 (frame 0). $
  73. 73. Inserting breakpoints You know your 'print' statements? print Turn them into breakpoints. Two ways: 2 : s/print/warn/ and -MCarp::REPL=warn Carp::REPL::repl
  74. 74. 18.sub c { 19. my $to_call = shift; 20. no strict 'refs'; 21. Carp::REPL::repl(); #Gimme a breakpoint here! 22. $to_call = quot;does_quot;.$to_call; 23. $to_call->(); 24.}
  75. 75. What's next for Carp::REPL? I have no idea. It's simple. It works.
  76. 76. Build web apps
  77. 77. Template::Declare A Pure Perl Templating Engine 2007 Talk Encore Presentation!
  78. 78. Perl has two big templating camps Perl 2
  79. 79. Template::Toolkit A DSL for templates DSL It's NOT Perl Why should I learn a new language for templates?
  80. 80. HTML::Mason There's Perl inside. Perl
  81. 81. HTML::Mason <mason><is><still> <full><of> <angle><brackets> < >< >< >< >< >< >
  82. 82. HTML::Mason </brackets></angle> </of></full> </still></is></mason> </ ></ ></ ></ ></ ></ >
  83. 83. I'm Just A Simple Perl Hacker Perl
  84. 84. I needed something more Perlish Perl
  85. 85. template '/pages/mypage.html' => sub { html { head {}; body { h1 {'Hey, this is text'}; } } };
  86. 86. template choices => page { h1 { 'My Choices' } dl { my $choices = Doxory::Model::ChoiceCollection->new; $choices->limit( column => 'asked_by', value => Jifty->web->current_user->id, ); while (my $c = $choices->next) { dt { $c->name, ' (', $c->asked_by->name, ')' } dd { b { $c->a } em { 'vs' } b { $c->b } } } } };
  87. 87. But! Content! Templates! ! ! Design! Code! ! ! OMGWTFBBQ!? !? THAT'S WRONG! !
  88. 88. The person who told you it's wrong was lying to you.
  89. 89. We're Perl hackers Perl
  90. 90. Why are we writing our templates in another language?
  91. 91. This is not 1997 1997
  92. 92. It’s 2008 2008
  93. 93. People use CSS for design now CSS
  94. 94. Programmers still have to make templates
  95. 95. Templates run like CODE
  96. 96. Because they ARE code
  97. 97. Let's use our CODING tools to work with them
  98. 98. How about Refactoring?
  99. 99. Have you ever tried to refactor HTML? HTML
  100. 100. template 'mypage.html' => page { h1 { 'Two choices' }; div { attr { class => 'item' }; h2 { 'Item 1'}; }; div { attr { class => 'item' }; h2 { 'Item 2'}; }; };
  101. 101. template 'mypage.html' => page { h1 { 'Two choices' }; for (quot;Item 1quot;, quot;Item 2quot;) { item($_); } }; sub item { my $content = shift; div { attr { class => 'item' }; h2 {$content}; }; }
  102. 102. We can refactor templates! !
  103. 103. Our HTML is magically valid HTML
  104. 104. (Syntax errors are... Syntax Errors) …
  105. 105. Object Oriented Templates
  106. 106. Subclassing It just works We're using Perl's symbol table Perl (Template::Declare's show() passes the class for you) Template::Declare show()
  107. 107. Mixins alias Some::Template::Library under '/path'; That's it.
  108. 108. Closures
  109. 109. Tags as Closures HTML tags take blocks of content HTML Our tag methods take blocks of Perl Perl They return closures when you want them They run and output their content when you want them to
  110. 110. sub h1 (&;$) { my $code = shift; ... if (defined wantarray) { return sub { ...closure around $code...}; } else { # Actually do our work, run $code and # return the output return $code->(); } }
  111. 111. What's next for Template::Declare? HTML Attribute Validation HTML Compile to .js js
  112. 112. CSS::Squish A compiler for Cascading Style Sheets CSS
  113. 113. The Problem Many small CSS Files CSS Easy to work with Painful to serve
  114. 114. The Problem One big CSS file CSS Painful to work with Easy to serve
  115. 115. How CSS works main.css: @import quot;yui-fonts.cssquot;; @import quot;base.cssquot;; @import quot;layout.cssquot;; @import quot;nav.cssquot;; @import quot;forms.cssquot;; @import quot;boxes.cssquot;; @import quot;login.cssquot;; ... CSS
  116. 116. How CSS works • Browser downloads CSS stylesheets listed in HTML • Browser processes each stylesheet for @include directives • Browser fetches each stylesheet found • This is slow. CSS::Squish
  117. 117. How CSS works To make CSS faster, you can tell browsers to cache stylesheets CSS ...then you have trouble if you want to update your styles Some people add datestamps to the stylesheet names: /css/mypagestyle.css?1210362379 CSS::Squish
  118. 118. How CSS::Squish works It pretends to be a browser. You give it the path to a stylesheet. It returns the fully computed stylesheet the browser would get eventually. You serve that file out to the user. CSS::Squish
  119. 119. How we use CSS::Squish Instead of: <link rel=quot;stylesheetquot; type=quot;text/cssquot; href=quot;main.css”/> We have this: <link rel=quot;stylesheetquot; type=quot;text/cssquot; href=quot;/ css/squished/ 4a50a85044a6ba727f7aa0683ac21f7e.css”/> CSS::Squish
  120. 120. How we use CSS::Squish If we have a cached copy of the squished CSS, name the ‘file’ as an MD5 of the content CSS MD5 Tell browsers to cache it forever When users load a page, they will always fetch the squished CSS if it’s changed. By magic CSS CSS::Squish
  121. 121. What’s next for CSS::Squish Refactor the MD5 hash bits from Jifty to CSS::Squish MD5 Jifty CSS::Squish What else do you want?
  122. 122. Ship software
  123. 123. App::ChangeLogger Gorgeous changelogs
  124. 124. We create a lot of software
  125. 125. (145 Projects in bps-public svn) 145
  126. 126. We’re not so good at doing releases
  127. 127. Lots of manual work
  128. 128. ShipIt can help with most of it ShipIt
  129. 129. What about Changelog?
  130. 130. svn log svn://svn.foo.com/MyProj > Changelog
  131. 131. Ship it! ShipIt
  132. 132. Ew. No. Ick. Wrong. Bad.
  133. 133. App::ChangeLogger
  134. 134. Two commands • sort-changelog • generate-changelog 2
  135. 135. Ok, three commands: • svn log --xml svn://svn.bestpractical.com/ App-Changelogger > changelog.raw.xml • ./bin/sort-changelog changelog.xml changelog.out.xml • bin/generate-changelog --generate changelog.out.xml Changelog 3
  136. 136. What's next for App::Changelogger? Use it on itself. (Release it) Store changelog metadata in repository Support for Git, Hg Git Hg Easier customization
  137. 137. Shipwright Build. Ship.
  138. 138. The Problem CPAN
  139. 139. The Problem Everything that is not CPAN : CPAN
  140. 140. We make RT RT
  141. 141. RT has Many Dependencies RT
  142. 142. Apache::DBI Digest::MD5 HTML::Scrubber Mail::Mailer Test::Warn Apache::Request Digest::base HTML::TokeParser Module::Refresh Text::ParseWords Apache::Session File::Find HTML::TreeBuilder Module::Versions::Report Text::Quoted CGI::Cookie File::Glob HTTP::Request::Common Net::SMTP Text::Template CGI::Fast File::ShareDir HTTP::Server::Simple PerlIO::eol Text::WikiFormat CGI::SpeedyCGI File::Spec HTTP::Server::Simple::Mason Pod::Usage Text::Wrapper CSS::Squish File::Temp IPC::Run Regexp::Common Time::HiRes Cache::Simple::TimedExpiry GD::Graph IPC::Run::SafeHandles Scalar::Util Time::ParseDate Calendar::Simple GD::Text LWP::UserAgent String::ShellQuote Tree::Simple Class::ReturnValue Getopt::Long Locale::Maketext Term::ReadKey UNIVERSAL::require DBD::Oracle GnuPG::Interface Locale::Maketext::Fuzzy Term::ReadLine WWW::Mechanize DBD::Pg HTML::Entities Locale::Maketext::Lexicon Test::Builder XML::RSS DBD::SQLite HTML::Form Log::Dispatch Test::Deep XML::Simple DBD::mysql HTML::FormatText Log::Dispatch::Perl Test::Expect DBIx::SearchBuilder HTML::Mason MIME::Entity Test::HTTP::Server::Simple Data::ICal HTML::RewriteAttributes MIME::Types Test::WWW::Mechanize
  143. 143. That’s just the non-core CPAN dependencies. Without all their dependencies.
  144. 144. 116 CPAN distributions once you do the recursion 116
  145. 145. And then there are the external libraries and programs
  146. 146. • perl • readline • expat • zlib • fontconfig • gnupg • freetype • mysql • libgd • postgresql • libjpeg • libpng
  147. 147. Plagger beats RT. (It has 135 CPAN deps) Plagger (Plagger 135 )
  148. 148. RT is hard to install RT
  149. 149. RT should be easy to install
  150. 150. All software should be easy to install
  151. 151. What Shipwright does Tracks all dependencies in version control (As far down as you want. I skip libc.) libc Shipwright
  152. 152. What Shipwright does Computes a full dependency order No more recursive CPAN installs CPAN Shipwright
  153. 153. What Shipwright does Keeps all packages in version control No more “that site is down” Shipwright
  154. 154. What Shipwright does Automates multi-package builds (No manual intervention) Shipwright
  155. 155. What Shipwright does Makes installed packages relocatable (Wraps all scripts and binaries) Shipwright
  156. 156. What Shipwright does Makes historical builds reproducible (No more “Oh. that API changed in 2.0”) API 2.0 Shipwright
  157. 157. Shipwright and CPAN CPAN-friendly CPAN (Not CPAN-only) CPAN CPAN dist import CPAN Automatic CPAN dependency resolution Full build ordering No more CPAN dependency hell. Shipwright CPAN
  158. 158. Shipwright and C Native support for autoconfiscated packages No support for magic C->C dependency resolutions C C Shipwright C
  159. 159. Shipwright and Ruby Not Ruby friendly :( Ruby No Gem support yet Gem Hackathon this weekend? Shipwright Ruby
  160. 160. What you can ship A platform-neutral source distribution Platform-specific binary distributions
  161. 161. Making a Shipwright Vessel svnadmin create file:///Users/jesse/shiprepo shipwright create --repository svn:file:///Users/jesse/shiprepo/myproject shipwright import --repository svn:file:///Users/jesse/shiprepo/myproject cpan:Plagger Go get a cup of coffee (Shipwright will chase all 135 dependencies) Shipwright 135 Shipwright
  162. 162. Building a Shipwright Vessel svn co file:///Users/jesse/shiprepo/myproject cd myproject ./bin/shipwright-builder (Possibly more coffee) ( ) tar czvf myproject.tgz /path/to/build Shipwright
  163. 163. Using a Shipwright Vessel • tar xzvf myproject.tgz c /usr/local/ myproject • ln -s /usr/local/myproject/bin/myprogram /usr/local/bin Shipwright
  164. 164. What's next for Shipwright? Build tool usability improvements Ruby support? Ruby
  165. 165. Get input from users
  166. 166. Date::Extract Get a date
  167. 167. The Problem
  168. 168. Pick up the drycleaning on tuesday after school
  169. 169. There are many Date / Time parsers on CPAN CPAN
  170. 170. Date::Manip
  171. 171. Time::ParseDate
  172. 172. Date::Parse
  173. 173. DateTime::Format::Natural
  174. 174. Each can parse dates and times
  175. 175. None of them are any good at finding dates in a block of text
  176. 176. Timezones are hard
  177. 177. Most parsers generate many false positives
  178. 178. use Date::Extract; my $arbitrary_text = <<EOF; I need to plan for my trip. On Sunday afternoon, I'll head on to taiwan. EOF my $parser = Date::Extract->new(); my $dt = $parser->extract($arbitrary_text) or die quot;No date found.quot;; warn $dt->ymd;
  179. 179. It's simple.
  180. 180. It's unsexy.
  181. 181. It's reliable.
  182. 182. What's next for Date::Extract? Parsing more obscure human-written dates? Date::Extract::Lingua::* ?
  183. 183. The Feedback Box Let users make suggestions everywhere
  184. 184. mailto: links?
  185. 185. getsatisfaction.com?
  186. 186. I give up.
  187. 187. Don't let your users give up.
  188. 188. Feedback is important!
  189. 189. Feedback can be easy!
  190. 190. If you make it easy for users to give you feedback...
  191. 191. You can capture lots of good information!
  192. 192. From: Jesse Vincent / Feedback <comment-373709-destygrypuju@tasks.hiveminder.com> Date: Mon, 12 May 2008 12:31:49 -0700 Subject: Up for grabs: I'd really like Hiveminder to do all my work for me! (#EFYG) Jesse Vincent <jesse@bestpractical.com> created a task and put it up for grabs: http://task.hm/EFYG I'd really like Hiveminder to do all my work for me! -- Private debugging information: Is a Pro user! HTTP_ACCEPT: application/xml, text/xml, */* HTTP_ACCEPT_ENCODING: gzip, deflate HTTP_ACCEPT_LANGUAGE: en-us HTTP_CONNECTION: keep-alive HTTP_COOKIE: JIFTY_SID_HIVEMINDER=b58e123456719fd411bb9f3a8123458f; HTTP_HOST: hiveminder.com HTTP_REFERER: http://hiveminder.com/todo/ HTTP_USER_AGENT: Mozilla/5.0 (Macintosh; U; Intel Mac OS X 10_5_2; en-us) AppleWebKit/526.5+ (KHTML, like Gecko) Version/3.1.1 Safari/525.18 HTTP_X_REQUESTED_WITH: XMLHttpRequest REMOTE_ADDR: 75.147.59.54 REMOTE_PORT: 35412 REQUEST_METHOD: POST REQUEST_URI: /todo/
  193. 193. Collect lots of feedback
  194. 194. Reply to lots of feedback
  195. 195. Conversations make users happy
  196. 196. Happy = Loyal
  197. 197. Own the inbox
  198. 198. Net::IMAP::Server An IMAP Server in Pure Perl Pure Perl IMAP Server
  199. 199. Why?
  200. 200. Offline Access
  201. 201. iPhone Access iPhone
  202. 202. Desktop Access
  203. 203. Really, we just like things that are sick and wrong.
  204. 204. Now Hiveminder users can take their tasks with them Hiveminder
  205. 205. Magic mailboxes
  206. 206. Update your tasks while offline
  207. 207. What sort of mailbox do you use with that?
  208. 208. mbox?
  209. 209. no
  210. 210. maildir?
  211. 211. no
  212. 212. How about Perl? Perl
  213. 213. Net::IMAP::Server
  214. 214. Complete RFC 3501 Implementation RFC 3501
  215. 215. Write your own backends
  216. 216. Let’s write one now
  217. 217. How about a Spam server? Spam
  218. 218. package Demo::IMAP::Auth; use base 'Net::IMAP::Server::DefaultAuth'; sub auth_plain { my ($self, $user, $pass ) = @_; # XXX DO AUTH CHECK return 1; }
  219. 219. package Demo::IMAP::Model; use base 'Net::IMAP::Server::DefaultModel'; sub init { my $self = shift; $self->root(Demo::IMAP::Mailbox->new()); $self->root->add_child( name => quot;INBOXquot;, is_inbox => 1); }
  220. 220. package Demo::IMAP::Mailbox; use base qw/Net::IMAP::Server::Mailbox/; my $msg = Net::IMAP::Server::Message->new(<<'EOM'); From: jesse@example.com To: user@example.com Subject: This is a test message! Hello. I am executive assistant to the director of Bear Stearns, a failed investment Bank. I have access to USD5,000,000. ... EOM sub load_data { my $self = shift; $self->add_message($msg); }
  221. 221. #!/usr/bin/perl use Net::IMAP::Server; Net::IMAP::Server->new( auth_class => quot;Demo::IMAP::Authquot;, model_class => quot;Demo::IMAP::Modelquot;, user => 'nobody', port => 143, ssl_port => 993 )->run();
  222. 222. It runs! Ship it! (Just add SSL certificates) SSL
  223. 223. with.hm Assign tasks by email
  224. 224. We wanted to make it easy to work with Hiveminder by email. Hiveminder
  225. 225. We had a few ideas... …
  226. 226. Cc:
  227. 227. Too clumsy
  228. 228. Bcc:
  229. 229. Too likely to break
  230. 230. Commands in the body
  231. 231. Too ugly
  232. 232. hm...
  233. 233. What could we do?
  234. 234. DNS Hacks! Everybody loves DNS hacks DNS
  235. 235. .hm
  236. 236. Hiveminder!
  237. 237. .hm
  238. 238. Heard and McDonald Islands!
  239. 239. with.hm
  240. 240. Send your email with Hiveminder Hiveminder
  241. 241. Wildcard MX Record! MX !
  242. 242. *.with.hm ➡ mail.hiveminder.com
  243. 243. An Example: From: jesse@bestpractical.com To: miyagawa@bulknews.net.with.hm Subject: Could you release a new version of plagger?
  244. 244. My mail server looks up bulknews.net.with.hm bulknews.net.with.hm
  245. 245. “Oh. That's handled by mail.hiveminder.com” mail.hiveminder.com
  246. 246. mail.hiveminder.com unwraps the address. mail.hiveminder.com
  247. 247. Hiveminder creates a task for miyagawa@bulknews.net miyagawa@bulknews.net
  248. 248. Hiveminder emails miyagawa@bulknews.net miyagawa@bulknews.net
  249. 249. Preventing Spam
  250. 250. miyagawa@bulknews.net.my- secret.with.hm .
  251. 251. I bet you can come up with even scarier uses of wildcard DNS. DNS
  252. 252. Thank you!
  1. A particular slide catching your eye?

    Clipping is a handy way to collect important slides you want to go back to later.

×