SlideShare une entreprise Scribd logo
1  sur  155
Télécharger pour lire hors ligne
App::Cmd
Writing Maintainable Commands
TMTOWTDI
There’s More Than
 One Way To Do It
Web
Web

• Mason
Web

• Mason
• Catalyst
Web

• Mason
• Catalyst
• CGI::Application
Web

• Mason
• Catalyst
• CGI::Application
• Maypole
Web

• Mason
• Catalyst
• CGI::Application
• Maypole
• Continuity
Web

• Mason              • RayApp
• Catalyst
• CGI::Application
• Maypole
• Continuity
Web

• Mason              • RayApp
• Catalyst           • Gantry
• CGI::Application
• Maypole
• Continuity
Web

• Mason              • RayApp
• Catalyst           • Gantry
• CGI::Application   • Tripletail
• Maypole
• Continuity
Web

• Mason              • RayApp
• Catalyst           • Gantry
• CGI::Application   • Tripletail
• Maypole            • CGI::ExApp
• Continuity
Web

• Mason              • RayApp
• Catalyst           • Gantry
• CGI::Application   • Tripletail
• Maypole            • CGI::ExApp
• Continuity         • OpenInteract
Daemons
Daemons

• POE
Daemons

• POE
• Danga
Daemons

• POE
• Danga
• Net::Server
Daemons

• POE
• Danga
• Net::Server
• Daemon::Generic
Daemons

• POE               • Proc::Daemon
• Danga
• Net::Server
• Daemon::Generic
Daemons

• POE               • Proc::Daemon
• Danga             • Net::Daemon
• Net::Server
• Daemon::Generic
Daemons

• POE               • Proc::Daemon
• Danga             • Net::Daemon
• Net::Server       • MooseX::Daemonize
• Daemon::Generic
Daemons

• POE               • Proc::Daemon
• Danga             • Net::Daemon
• Net::Server       • MooseX::Daemonize
• Daemon::Generic   • Event
TMTOWTDI
TMTOWTDI


• All the big problem sets have a few solutions!
TMTOWTDI


• All the big problem sets have a few solutions!
• So, when I needed to write a CLI app, I
  checked CPAN...
Command-Line Apps
Command-Line Apps


• App::CLI
Command-Line Apps
Command-Line Apps



    :-(
Everybody writes
command-line apps!
Why are there no
  good tools?
Second-Class Citizens
Second-Class Citizens

• That’s how we view them.
Second-Class Citizens

• That’s how we view them.
• They’re
Second-Class Citizens

• That’s how we view them.
• They’re
 • hard to test
Second-Class Citizens

• That’s how we view them.
• They’re
 • hard to test
 • not reusable components
Second-Class Citizens

• That’s how we view them.
• They’re
 • hard to test
 • not reusable components
 • hard to add more behavior later
Here’s an Example
Example Script


$ sink 30min “server mx-pa-1 crashed!”
Example Script

$ sink --list

who   | time | event
------+-------+----------------------------
rjbs | 30min | server mx-pa-1 crashed!
Example Script

GetOptions(%opt, ...);

if ($opt{list}) {
  die if @ARGV;
  @events = Events->get_all;
} else {
  my ($duration, $desc) = @ARGV;
  Event->new($duration, $desc);
}
Example Script

$ sink --list --user jcap

who   | time | event
------+-------+----------------------------
jcap | 2hr    | redeploy exigency subsystem
Example Script
GetOptions(%opt, ...);

if ($opt{list}) {
  die if @ARGV;
  @events = $opt{user}
          ? Events->get(user => $opt{user})
          : Events->get_all;
} else {
  my ($duration, $desc) = @ARGV;
  Event->new($duration, $desc);
}
Example Script
GetOptions(%opt, ...);

if ($opt{list}) {
  die if @ARGV;
  @events = $opt{user}
          ? Events->get(user => $opt{user})
          : Events->get_all;
} else {
  my ($duration, $desc) = @ARGV;
  die if $opt{user};
  Event->new($duration, $desc);
}
Example Script

$ sink --start ‘putting out oil fire‘
Event begun! use --finish to finish event

$ sink --list --open
18. putting out oil fire

$ sink --finish 18
Event finished! Total time taken: 23 min
Insult to Injury
Insult to Injury

• ...well, that’s going to take a lot of
  testing.
Insult to Injury

• ...well, that’s going to take a lot of
  testing.
• How can we test it?
Insult to Injury

• ...well, that’s going to take a lot of
  testing.
• How can we test it?
• my $output = `sink @args`;
Insult to Injury

• ...well, that’s going to take a lot of
  testing.
• How can we test it?
• my $output = `sink @args`;
• IPC::Run3 (or one of those)
Here’s a Solution
Command Breakdown


$ sink do --for 1hr --ago 1d ‘rebuild raid’
Command Breakdown


$ sink do --for 1hr --ago 1d ‘rebuild raid’

  App
Command Breakdown


$ sink do --for 1hr --ago 1d ‘rebuild raid’

    Command
Command Breakdown


$ sink do --for 1hr --ago 1d ‘rebuild raid’

                Options
Command Breakdown


$ sink do --for 1hr --ago 1d ‘rebuild raid’

                                 Args
Command Breakdown


$ sink do --for 1hr --ago 1d ‘rebuild raid’
“do” command
“do” command
sub run {
“do” command
sub run {
  my ($self, $opt, $args) = @_;
“do” command
sub run {
  my ($self, $opt, $args) = @_;
“do” command
sub run {
  my ($self, $opt, $args) = @_;

  my $start   = parse_ago($opt->{ago});
“do” command
sub run {
  my ($self, $opt, $args) = @_;

  my $start = parse_ago($opt->{ago});
  my $length = parse_duration($opt->{for});
“do” command
sub run {
  my ($self, $opt, $args) = @_;

  my $start = parse_ago($opt->{ago});
  my $length = parse_duration($opt->{for});
  my $desc   = $args->[0];
“do” command
sub run {
  my ($self, $opt, $args) = @_;

  my $start = parse_ago($opt->{ago});
  my $length = parse_duration($opt->{for});
  my $desc   = $args->[0];
“do” command
sub run {
  my ($self, $opt, $args) = @_;

  my $start = parse_ago($opt->{ago});
  my $length = parse_duration($opt->{for});
  my $desc   = $args->[0];

  Sink::Event->create(
“do” command
sub run {
  my ($self, $opt, $args) = @_;

  my $start = parse_ago($opt->{ago});
  my $length = parse_duration($opt->{for});
  my $desc   = $args->[0];

  Sink::Event->create(
    start => $start,
“do” command
sub run {
  my ($self, $opt, $args) = @_;

  my $start = parse_ago($opt->{ago});
  my $length = parse_duration($opt->{for});
  my $desc   = $args->[0];

  Sink::Event->create(
    start => $start,
    finish => $start + $length,
“do” command
sub run {
  my ($self, $opt, $args) = @_;

  my $start = parse_ago($opt->{ago});
  my $length = parse_duration($opt->{for});
  my $desc   = $args->[0];

  Sink::Event->create(
    start => $start,
    finish => $start + $length,
    desc   => $desc;
“do” command
sub run {
  my ($self, $opt, $args) = @_;

  my $start = parse_ago($opt->{ago});
  my $length = parse_duration($opt->{for});
  my $desc   = $args->[0];

  Sink::Event->create(
     start => $start,
     finish => $start + $length,
     desc   => $desc;
  );
“do” command
sub run {
  my ($self, $opt, $args) = @_;

  my $start = parse_ago($opt->{ago});
  my $length = parse_duration($opt->{for});
  my $desc   = $args->[0];

  Sink::Event->create(
     start => $start,
     finish => $start + $length,
     desc   => $desc;
  );
“do” command
sub run {
  my ($self, $opt, $args) = @_;

  my $start = parse_ago($opt->{ago});
  my $length = parse_duration($opt->{for});
  my $desc   = $args->[0];

  Sink::Event->create(
     start => $start,
     finish => $start + $length,
     desc   => $desc;
  );

  print “event created!”;
“do” command
sub run {
  my ($self, $opt, $args) = @_;

    my $start = parse_ago($opt->{ago});
    my $length = parse_duration($opt->{for});
    my $desc   = $args->[0];

    Sink::Event->create(
       start => $start,
       finish => $start + $length,
       desc   => $desc;
    );

    print “event created!”;
}
“do” command
“do” command

sub opt_desc {
“do” command

sub opt_desc {
  [ “start=s”, “when you started doing this” ],
“do” command

sub opt_desc {
  [ “start=s”, “when you started doing this” ],
  [ “for=s”,   “how long you did this for”,
“do” command

sub opt_desc {
  [ “start=s”, “when you started doing this” ],
  [ “for=s”,   “how long you did this for”,
    { required => 1} ],
“do” command

sub opt_desc {
  [ “start=s”, “when you started doing this” ],
  [ “for=s”,   “how long you did this for”,
    { required => 1} ],
}
“do” command
“do” command

sub validate_args {
“do” command

sub validate_args {
  my ($self, $opt, $args) = @_;
“do” command

sub validate_args {
  my ($self, $opt, $args) = @_;
“do” command

sub validate_args {
  my ($self, $opt, $args) = @_;

  if (@$args != 1) {
“do” command

sub validate_args {
  my ($self, $opt, $args) = @_;

  if (@$args != 1) {
    $self->usage_error(“provide one argument”);
“do” command

sub validate_args {
  my ($self, $opt, $args) = @_;

  if (@$args != 1) {
    $self->usage_error(“provide one argument”);
  }
“do” command

sub validate_args {
  my ($self, $opt, $args) = @_;

    if (@$args != 1) {
      $self->usage_error(“provide one argument”);
    }
}
package Sink::Command::Do;
use base ‘App::Cmd::Command’;

sub opt_desc {
  [ “start=s”, “when you started doing this” ],
  [ “for=s”,   “how long you did this for”,
    { required => 1} ],
}

sub validate_args {
  my ($self, $opt, $args) = @_;

    if (@$args != 1) {
      $self->usage_error(“provide one argument”);
    }
}

sub run {
  my ($self, $opt, $args) = @_;

    my $start = parse_ago($opt->{ago});
    my $length = parse_duration($opt->{for});
    my $desc   = $args->[0];

    Sink::Event->create(
       start => $start,
       finish => $start + $length,
       desc   => $desc;
    );

    print “event created!”;
}

1;
package Sink::Command::Do;
use base ‘App::Cmd::Command’;

sub opt_desc {
  [ “start=s”, “when you started doing this” ],
  [ “for=s”,   “how long you did this for”,
    { required => 1} ],
}

sub validate_args {
  my ($self, $opt, $args) = @_;

    if (@$args != 1) {
      $self->usage_error(“provide one argument”);
    }
}

sub run {
  my ($self, $opt, $args) = @_;

    my $start = parse_ago($opt->{ago});
    my $length = parse_duration($opt->{for});
    my $desc   = $args->[0];

    Sink::Event->create(
       start => $start,
       finish => $start + $length,
       desc   => $desc;
    );

    print “event created!”;
}

1;
Extra Scaffolding
Extra Scaffolding
package Sink;
Extra Scaffolding
package Sink;
use base ‘App::Cmd’;
Extra Scaffolding
package Sink;
use base ‘App::Cmd’;




1;
Extra Scaffolding


use Sink;
Sink->run;
Testing Your App
Testing App::Cmd
Testing App::Cmd
use Test::More tests => 3;
Testing App::Cmd
use Test::More tests => 3;
use Test::Output;
Testing App::Cmd
use Test::More tests => 3;
use Test::Output;
Testing App::Cmd
use Test::More tests => 3;
use Test::Output;

my $error;
Testing App::Cmd
use Test::More tests => 3;
use Test::Output;

my $error;
my $stdout = do {
Testing App::Cmd
use Test::More tests => 3;
use Test::Output;

my $error;
my $stdout = do {
  local @ARGV = qw(do --for 8hr ‘sleeping’);
Testing App::Cmd
use Test::More tests => 3;
use Test::Output;

my $error;
my $stdout = do {
  local @ARGV = qw(do --for 8hr ‘sleeping’);
  stdout_from(sub {
Testing App::Cmd
use Test::More tests => 3;
use Test::Output;

my $error;
my $stdout = do {
  local @ARGV = qw(do --for 8hr ‘sleeping’);
  stdout_from(sub {
    eval { Sink->run; 1 } or $error = $@;
Testing App::Cmd
use Test::More tests => 3;
use Test::Output;

my $error;
my $stdout = do {
  local @ARGV = qw(do --for 8hr ‘sleeping’);
  stdout_from(sub {
    eval { Sink->run; 1 } or $error = $@;
  });
Testing App::Cmd
use Test::More tests => 3;
use Test::Output;

my $error;
my $stdout = do {
  local @ARGV = qw(do --for 8hr ‘sleeping’);
  stdout_from(sub {
    eval { Sink->run; 1 } or $error = $@;
  });
}
Testing App::Cmd
use Test::More tests => 3;
use Test::Output;

my $error;
my $stdout = do {
  local @ARGV = qw(do --for 8hr ‘sleeping’);
  stdout_from(sub {
    eval { Sink->run; 1 } or $error = $@;
  });
}
Testing App::Cmd
use Test::More tests => 3;
use Test::Output;

my $error;
my $stdout = do {
  local @ARGV = qw(do --for 8hr ‘sleeping’);
  stdout_from(sub {
    eval { Sink->run; 1 } or $error = $@;
  });
}

like $stdout, qr/^event created!$/;
Testing App::Cmd
use Test::More tests => 3;
use Test::Output;

my $error;
my $stdout = do {
  local @ARGV = qw(do --for 8hr ‘sleeping’);
  stdout_from(sub {
    eval { Sink->run; 1 } or $error = $@;
  });
}

like $stdout, qr/^event created!$/;
is   Sink::Event->get_count, 1;
Testing App::Cmd
use Test::More tests => 3;
use Test::Output;

my $error;
my $stdout = do {
  local @ARGV = qw(do --for 8hr ‘sleeping’);
  stdout_from(sub {
    eval { Sink->run; 1 } or $error = $@;
  });
}

like $stdout, qr/^event created!$/;
is   Sink::Event->get_count, 1;
ok   ! $error;
Testing App::Cmd

use Test::More tests => 3;
use Test::App::Cmd;
use Sink;

my ($stdout, $error) = test_app(
   Sink => qw(do --for 8hr ‘sleeping’)
);

like $stdout, qr/^event created!$/;
is   Sink::Event->get_count, 1;
ok   ! $error;
Testing App::Cmd

use Test::More tests => π;
use Sink::Command::Do;

eval {
   Sink::Command::Do->validate_args(
      { for => ‘1hr’ },
      [ 1, 2, 3 ],
   );
};

like $@, qr/one arg/;
Growing Your App
Command Breakdown


$ sink do --for 1hr --ago 1d ‘rebuild raid’
Command Breakdown


$ sink do --for 1hr --ago 1d ‘rebuild raid’

    Command
package Sink::Command::List;
use base ‘App::Cmd::Command’;

sub opt_desc { ... }

sub validate_args { ... }

sub run { ... }

1;
package Sink::Command::List;
use base ‘App::Cmd::Command’;

sub opt_desc {
  [ “open”,     “only unfinished events”    ],
  [ “user|u=s”, “only events for this user” ],
}

sub validate_args {
  shift->usage_error(’no args allowed’)
    if @{ $_[1] }
}

sub run { ... }

1;
package Sink::Command::Start;
use base ‘App::Cmd::Command’;

sub opt_desc { ... }

sub validate_args { ... }

sub run { ... }

1;
package Sink::Command::Start;
use base ‘App::Cmd::Command’;

sub opt_desc { return }

sub validate_args {
  shift->usage_error(’one args required’)
    if @{ $_[1] } != 1
}

sub run { ... }

1;
More Commands!

$ sink do --for 1hr --ago 1d ‘rebuild raid’

$ sink list --open

$ sink start ‘porting PHP to ASP.NET’
More Commands!
$ sink
sink help <command>

Available commands:
  commands: list the application’s commands
      help: display a command’s help screen

       do: (unknown)
     list: (unknown)
    start: (unknown)
Command Listing

package Sink::Command::Start;

=head1 NAME

Sink::Command::Start - start a new task

=cut
Command Listing


package Sink::Command::Start;

sub abstract { ‘start a new task’; }
Command Listing

$ sink commands

Available commands:
  commands: list the application’s commands
      help: display a command’s help screen

       do: record that you did something
     list: list existing events
    start: start a new task
Command Listing
Command Listing

$ sink help list
Command Listing

$ sink help list
Command Listing

$ sink help list

sink list [long options...]
Command Listing

$ sink help list

sink list [long options...]
    -u --user     only events for this user
Command Listing

$ sink help list

sink list [long options...]
    -u --user     only events for this user
    --open        only unfinished events
Core Commands
Core Commands

• Where did “help” and “commands”
  come from?
Core Commands

• Where did “help” and “commands”
  come from?
• App::Cmd::Command::help
Core Commands

• Where did “help” and “commands”
  come from?
• App::Cmd::Command::help
• App::Cmd::Command::commands
Default Command
package Sink;
use base ‘App::Cmd’;




1;
Default Command
package Sink;
use base ‘App::Cmd’;

sub default_command { ‘help’ } # default




1;
Default Command
package Sink;
use base ‘App::Cmd’;

sub default_command { ‘list’ }




1;
One-Command
 Applications
Simple Example


$ ckmail check -a work -a home
No new mail.
Simple Example


$ ckmail -a work -a home
No new mail.
The Lousy Way
The Lousy Way

• create Ckmail::Command::Check
The Lousy Way

• create Ckmail::Command::Check
• make empty Ckmail.pm
The Lousy Way

• create Ckmail::Command::Check
• make empty Ckmail.pm
• make “check” the default command
The Simple Way

package Ckmail::Command::Check;
use base ‘App::Cmd::Command’;

sub opt_desc { ... }

sub run { ... }

1;
The Simple Way

package Ckmail::Command::Check;
use base ‘App::Cmd::Simple’;

sub opt_desc { ... }

sub run { ... }

1;
The Simple Way


use Ckmail;
Ckmail->run;
The Simple Way


use Ckmail::Command::Check;
Ckmail::Command::Check->run;
App::Cmd::Simple
App::Cmd::Simple

• You write a command...
App::Cmd::Simple

• You write a command...
• ...but you use it like an App::Cmd.
App::Cmd::Simple

• You write a command...
• ...but you use it like an App::Cmd.
• Later, you can just demote it.
Any
Questions?
Thank
 You!

Contenu connexe

Tendances

Exploiting the newer perl to improve your plugins
Exploiting the newer perl to improve your pluginsExploiting the newer perl to improve your plugins
Exploiting the newer perl to improve your plugins
Marian Marinov
 
Perl web frameworks
Perl web frameworksPerl web frameworks
Perl web frameworks
diego_k
 
Building Better Applications with Data::Manager
Building Better Applications with Data::ManagerBuilding Better Applications with Data::Manager
Building Better Applications with Data::Manager
Jay Shirley
 
Smolder @Silex
Smolder @SilexSmolder @Silex
Smolder @Silex
Jeen Lee
 

Tendances (20)

Fewer cables
Fewer cablesFewer cables
Fewer cables
 
Command
CommandCommand
Command
 
Any event intro
Any event introAny event intro
Any event intro
 
Keep it simple web development stack
Keep it simple web development stackKeep it simple web development stack
Keep it simple web development stack
 
Modern Getopt for Command Line Processing in Perl
Modern Getopt for Command Line Processing in PerlModern Getopt for Command Line Processing in Perl
Modern Getopt for Command Line Processing in Perl
 
Asynchronous Programming FTW! 2 (with AnyEvent)
Asynchronous Programming FTW! 2 (with AnyEvent)Asynchronous Programming FTW! 2 (with AnyEvent)
Asynchronous Programming FTW! 2 (with AnyEvent)
 
Exploiting the newer perl to improve your plugins
Exploiting the newer perl to improve your pluginsExploiting the newer perl to improve your plugins
Exploiting the newer perl to improve your plugins
 
Perl web frameworks
Perl web frameworksPerl web frameworks
Perl web frameworks
 
The promise of asynchronous php
The promise of asynchronous phpThe promise of asynchronous php
The promise of asynchronous php
 
Building Better Applications with Data::Manager
Building Better Applications with Data::ManagerBuilding Better Applications with Data::Manager
Building Better Applications with Data::Manager
 
Smolder @Silex
Smolder @SilexSmolder @Silex
Smolder @Silex
 
My app is secure... I think
My app is secure... I thinkMy app is secure... I think
My app is secure... I think
 
10 Catalyst Tips
10 Catalyst Tips10 Catalyst Tips
10 Catalyst Tips
 
Perl 6 by example
Perl 6 by examplePerl 6 by example
Perl 6 by example
 
Hypers and Gathers and Takes! Oh my!
Hypers and Gathers and Takes! Oh my!Hypers and Gathers and Takes! Oh my!
Hypers and Gathers and Takes! Oh my!
 
Logstash for SEO: come monitorare i Log del Web Server in realtime
Logstash for SEO: come monitorare i Log del Web Server in realtimeLogstash for SEO: come monitorare i Log del Web Server in realtime
Logstash for SEO: come monitorare i Log del Web Server in realtime
 
Teaching Your Machine To Find Fraudsters
Teaching Your Machine To Find FraudstersTeaching Your Machine To Find Fraudsters
Teaching Your Machine To Find Fraudsters
 
The promise of asynchronous php
The promise of asynchronous phpThe promise of asynchronous php
The promise of asynchronous php
 
Anyevent
AnyeventAnyevent
Anyevent
 
Debugging: Rules And Tools - PHPTek 11 Version
Debugging: Rules And Tools - PHPTek 11 VersionDebugging: Rules And Tools - PHPTek 11 Version
Debugging: Rules And Tools - PHPTek 11 Version
 

En vedette

Windows command prompt a to z
Windows command prompt a to zWindows command prompt a to z
Windows command prompt a to z
Subuh Kurniawan
 
Sly and the RoarVM: Exploring the Manycore Future of Programming
Sly and the RoarVM: Exploring the Manycore Future of ProgrammingSly and the RoarVM: Exploring the Manycore Future of Programming
Sly and the RoarVM: Exploring the Manycore Future of Programming
Stefan Marr
 
Fixing mobile phones
Fixing mobile phonesFixing mobile phones
Fixing mobile phones
theviolet
 
Powershell
PowershellPowershell
Powershell
UGAIA
 
Comandos ms dos(simbolo de sistema)
Comandos ms dos(simbolo de sistema)Comandos ms dos(simbolo de sistema)
Comandos ms dos(simbolo de sistema)
castillodavid
 

En vedette (18)

Windows command prompt a to z
Windows command prompt a to zWindows command prompt a to z
Windows command prompt a to z
 
CMD Command
CMD CommandCMD Command
CMD Command
 
cmd commands
cmd commandscmd commands
cmd commands
 
Sly and the RoarVM: Exploring the Manycore Future of Programming
Sly and the RoarVM: Exploring the Manycore Future of ProgrammingSly and the RoarVM: Exploring the Manycore Future of Programming
Sly and the RoarVM: Exploring the Manycore Future of Programming
 
CMD in 2013
CMD in 2013CMD in 2013
CMD in 2013
 
12 Reasons Why Hot Entrepreneurs Fail
12 Reasons Why Hot Entrepreneurs Fail12 Reasons Why Hot Entrepreneurs Fail
12 Reasons Why Hot Entrepreneurs Fail
 
Fixing mobile phones
Fixing mobile phonesFixing mobile phones
Fixing mobile phones
 
SyScan 2015 Bonus Slides - death of the vmsize=0 dyld trick
SyScan 2015 Bonus Slides - death of the vmsize=0 dyld trickSyScan 2015 Bonus Slides - death of the vmsize=0 dyld trick
SyScan 2015 Bonus Slides - death of the vmsize=0 dyld trick
 
Introduction to Processing and creative coding
Introduction to Processing and creative codingIntroduction to Processing and creative coding
Introduction to Processing and creative coding
 
Cmd v2.0
Cmd v2.0Cmd v2.0
Cmd v2.0
 
Powershell
PowershellPowershell
Powershell
 
DNS,SMTP and POP3
DNS,SMTP and POP3DNS,SMTP and POP3
DNS,SMTP and POP3
 
Ensuring data integrity in pharmaceutical environment
Ensuring data integrity in pharmaceutical environmentEnsuring data integrity in pharmaceutical environment
Ensuring data integrity in pharmaceutical environment
 
Chapter 03 - Program Coding and Design
Chapter 03 - Program Coding and DesignChapter 03 - Program Coding and Design
Chapter 03 - Program Coding and Design
 
Junos vs ios Troubleshooting comands
Junos vs ios Troubleshooting comands Junos vs ios Troubleshooting comands
Junos vs ios Troubleshooting comands
 
Pharma data integrity
Pharma data integrityPharma data integrity
Pharma data integrity
 
Introduction to Coding
Introduction to CodingIntroduction to Coding
Introduction to Coding
 
Comandos ms dos(simbolo de sistema)
Comandos ms dos(simbolo de sistema)Comandos ms dos(simbolo de sistema)
Comandos ms dos(simbolo de sistema)
 

Similaire à Writing Modular Command-line Apps with App::Cmd

Perl.Hacks.On.Vim
Perl.Hacks.On.VimPerl.Hacks.On.Vim
Perl.Hacks.On.Vim
Lin Yo-An
 
Good Evils In Perl
Good Evils In PerlGood Evils In Perl
Good Evils In Perl
Kang-min Liu
 
The Dom Scripting Toolkit J Query
The Dom Scripting Toolkit J QueryThe Dom Scripting Toolkit J Query
The Dom Scripting Toolkit J Query
QConLondon2008
 
Beijing Perl Workshop 2008 Hiveminder Secret Sauce
Beijing Perl Workshop 2008 Hiveminder Secret SauceBeijing Perl Workshop 2008 Hiveminder Secret Sauce
Beijing Perl Workshop 2008 Hiveminder Secret Sauce
Jesse Vincent
 
Good Evils In Perl (Yapc Asia)
Good Evils In Perl (Yapc Asia)Good Evils In Perl (Yapc Asia)
Good Evils In Perl (Yapc Asia)
Kang-min Liu
 
Barely Legal Xxx Perl Presentation
Barely Legal Xxx Perl PresentationBarely Legal Xxx Perl Presentation
Barely Legal Xxx Perl Presentation
Attila Balazs
 
Remy Sharp The DOM scripting toolkit jQuery
Remy Sharp The DOM scripting toolkit jQueryRemy Sharp The DOM scripting toolkit jQuery
Remy Sharp The DOM scripting toolkit jQuery
deimos
 
Why Perl, when you can use bash+awk+sed? :P
Why Perl, when you can use bash+awk+sed? :PWhy Perl, when you can use bash+awk+sed? :P
Why Perl, when you can use bash+awk+sed? :P
Luciano Rocha
 
R57php 1231677414471772-2
R57php 1231677414471772-2R57php 1231677414471772-2
R57php 1231677414471772-2
ady36
 

Similaire à Writing Modular Command-line Apps with App::Cmd (20)

Perl.Hacks.On.Vim
Perl.Hacks.On.VimPerl.Hacks.On.Vim
Perl.Hacks.On.Vim
 
Dealing with Legacy Perl Code - Peter Scott
Dealing with Legacy Perl Code - Peter ScottDealing with Legacy Perl Code - Peter Scott
Dealing with Legacy Perl Code - Peter Scott
 
What's up with Prototype and script.aculo.us?
What's up with Prototype and script.aculo.us?What's up with Prototype and script.aculo.us?
What's up with Prototype and script.aculo.us?
 
Good Evils In Perl
Good Evils In PerlGood Evils In Perl
Good Evils In Perl
 
The $path to knowledge: What little it take to unit-test Perl.
The $path to knowledge: What little it take to unit-test Perl.The $path to knowledge: What little it take to unit-test Perl.
The $path to knowledge: What little it take to unit-test Perl.
 
Rack Middleware
Rack MiddlewareRack Middleware
Rack Middleware
 
The Dom Scripting Toolkit J Query
The Dom Scripting Toolkit J QueryThe Dom Scripting Toolkit J Query
The Dom Scripting Toolkit J Query
 
Beijing Perl Workshop 2008 Hiveminder Secret Sauce
Beijing Perl Workshop 2008 Hiveminder Secret SauceBeijing Perl Workshop 2008 Hiveminder Secret Sauce
Beijing Perl Workshop 2008 Hiveminder Secret Sauce
 
EC2
EC2EC2
EC2
 
Method::Signatures
Method::SignaturesMethod::Signatures
Method::Signatures
 
Good Evils In Perl (Yapc Asia)
Good Evils In Perl (Yapc Asia)Good Evils In Perl (Yapc Asia)
Good Evils In Perl (Yapc Asia)
 
Crafting Custom Interfaces with Sub::Exporter
Crafting Custom Interfaces with Sub::ExporterCrafting Custom Interfaces with Sub::Exporter
Crafting Custom Interfaces with Sub::Exporter
 
Perl Sucks - and what to do about it
Perl Sucks - and what to do about itPerl Sucks - and what to do about it
Perl Sucks - and what to do about it
 
Barely Legal Xxx Perl Presentation
Barely Legal Xxx Perl PresentationBarely Legal Xxx Perl Presentation
Barely Legal Xxx Perl Presentation
 
Postman On Steroids
Postman On SteroidsPostman On Steroids
Postman On Steroids
 
Vim Hacks
Vim HacksVim Hacks
Vim Hacks
 
Vim Hacks
Vim HacksVim Hacks
Vim Hacks
 
Remy Sharp The DOM scripting toolkit jQuery
Remy Sharp The DOM scripting toolkit jQueryRemy Sharp The DOM scripting toolkit jQuery
Remy Sharp The DOM scripting toolkit jQuery
 
Why Perl, when you can use bash+awk+sed? :P
Why Perl, when you can use bash+awk+sed? :PWhy Perl, when you can use bash+awk+sed? :P
Why Perl, when you can use bash+awk+sed? :P
 
R57php 1231677414471772-2
R57php 1231677414471772-2R57php 1231677414471772-2
R57php 1231677414471772-2
 

Plus de Ricardo Signes

Perl 5: Today, Tomorrow, and Christmas
Perl 5: Today, Tomorrow, and ChristmasPerl 5: Today, Tomorrow, and Christmas
Perl 5: Today, Tomorrow, and Christmas
Ricardo Signes
 
Perl 5.14 for Pragmatists
Perl 5.14 for PragmatistsPerl 5.14 for Pragmatists
Perl 5.14 for Pragmatists
Ricardo Signes
 
Dist::Zilla - Maximum Overkill for CPAN Distributions
Dist::Zilla - Maximum Overkill for CPAN DistributionsDist::Zilla - Maximum Overkill for CPAN Distributions
Dist::Zilla - Maximum Overkill for CPAN Distributions
Ricardo Signes
 
Perl 5.12 for Everyday Use
Perl 5.12 for Everyday UsePerl 5.12 for Everyday Use
Perl 5.12 for Everyday Use
Ricardo Signes
 
Antediluvian Unix: A Guide to Unix Fundamentals
Antediluvian Unix: A Guide to Unix FundamentalsAntediluvian Unix: A Guide to Unix Fundamentals
Antediluvian Unix: A Guide to Unix Fundamentals
Ricardo Signes
 

Plus de Ricardo Signes (10)

Perl 5: Today, Tomorrow, and Christmas
Perl 5: Today, Tomorrow, and ChristmasPerl 5: Today, Tomorrow, and Christmas
Perl 5: Today, Tomorrow, and Christmas
 
What's New in Perl? v5.10 - v5.16
What's New in Perl?  v5.10 - v5.16What's New in Perl?  v5.10 - v5.16
What's New in Perl? v5.10 - v5.16
 
Perl 5.14 for Pragmatists
Perl 5.14 for PragmatistsPerl 5.14 for Pragmatists
Perl 5.14 for Pragmatists
 
Dist::Zilla - Maximum Overkill for CPAN Distributions
Dist::Zilla - Maximum Overkill for CPAN DistributionsDist::Zilla - Maximum Overkill for CPAN Distributions
Dist::Zilla - Maximum Overkill for CPAN Distributions
 
Perl 5.12 for Everyday Use
Perl 5.12 for Everyday UsePerl 5.12 for Everyday Use
Perl 5.12 for Everyday Use
 
i &lt;3 email
i &lt;3 emaili &lt;3 email
i &lt;3 email
 
Dist::Zilla
Dist::ZillaDist::Zilla
Dist::Zilla
 
Antediluvian Unix: A Guide to Unix Fundamentals
Antediluvian Unix: A Guide to Unix FundamentalsAntediluvian Unix: A Guide to Unix Fundamentals
Antediluvian Unix: A Guide to Unix Fundamentals
 
Perl 5.10 for People Who Aren't Totally Insane
Perl 5.10 for People Who Aren't Totally InsanePerl 5.10 for People Who Aren't Totally Insane
Perl 5.10 for People Who Aren't Totally Insane
 
How I Learned to Stop Worrying and Love Email::: The 2007 PEP Talk!!
How I Learned to Stop Worrying and Love Email::: The 2007 PEP Talk!!How I Learned to Stop Worrying and Love Email::: The 2007 PEP Talk!!
How I Learned to Stop Worrying and Love Email::: The 2007 PEP Talk!!
 

Dernier

Architecting Cloud Native Applications
Architecting Cloud Native ApplicationsArchitecting Cloud Native Applications
Architecting Cloud Native Applications
WSO2
 
Cloud Frontiers: A Deep Dive into Serverless Spatial Data and FME
Cloud Frontiers:  A Deep Dive into Serverless Spatial Data and FMECloud Frontiers:  A Deep Dive into Serverless Spatial Data and FME
Cloud Frontiers: A Deep Dive into Serverless Spatial Data and FME
Safe Software
 
Modular Monolith - a Practical Alternative to Microservices @ Devoxx UK 2024
Modular Monolith - a Practical Alternative to Microservices @ Devoxx UK 2024Modular Monolith - a Practical Alternative to Microservices @ Devoxx UK 2024
Modular Monolith - a Practical Alternative to Microservices @ Devoxx UK 2024
Victor Rentea
 
Cloud Frontiers: A Deep Dive into Serverless Spatial Data and FME
Cloud Frontiers:  A Deep Dive into Serverless Spatial Data and FMECloud Frontiers:  A Deep Dive into Serverless Spatial Data and FME
Cloud Frontiers: A Deep Dive into Serverless Spatial Data and FME
Safe Software
 
+971581248768>> SAFE AND ORIGINAL ABORTION PILLS FOR SALE IN DUBAI AND ABUDHA...
+971581248768>> SAFE AND ORIGINAL ABORTION PILLS FOR SALE IN DUBAI AND ABUDHA...+971581248768>> SAFE AND ORIGINAL ABORTION PILLS FOR SALE IN DUBAI AND ABUDHA...
+971581248768>> SAFE AND ORIGINAL ABORTION PILLS FOR SALE IN DUBAI AND ABUDHA...
?#DUbAI#??##{{(☎️+971_581248768%)**%*]'#abortion pills for sale in dubai@
 

Dernier (20)

Architecting Cloud Native Applications
Architecting Cloud Native ApplicationsArchitecting Cloud Native Applications
Architecting Cloud Native Applications
 
Apidays New York 2024 - APIs in 2030: The Risk of Technological Sleepwalk by ...
Apidays New York 2024 - APIs in 2030: The Risk of Technological Sleepwalk by ...Apidays New York 2024 - APIs in 2030: The Risk of Technological Sleepwalk by ...
Apidays New York 2024 - APIs in 2030: The Risk of Technological Sleepwalk by ...
 
Exploring the Future Potential of AI-Enabled Smartphone Processors
Exploring the Future Potential of AI-Enabled Smartphone ProcessorsExploring the Future Potential of AI-Enabled Smartphone Processors
Exploring the Future Potential of AI-Enabled Smartphone Processors
 
MS Copilot expands with MS Graph connectors
MS Copilot expands with MS Graph connectorsMS Copilot expands with MS Graph connectors
MS Copilot expands with MS Graph connectors
 
Apidays New York 2024 - The value of a flexible API Management solution for O...
Apidays New York 2024 - The value of a flexible API Management solution for O...Apidays New York 2024 - The value of a flexible API Management solution for O...
Apidays New York 2024 - The value of a flexible API Management solution for O...
 
FWD Group - Insurer Innovation Award 2024
FWD Group - Insurer Innovation Award 2024FWD Group - Insurer Innovation Award 2024
FWD Group - Insurer Innovation Award 2024
 
Rising Above_ Dubai Floods and the Fortitude of Dubai International Airport.pdf
Rising Above_ Dubai Floods and the Fortitude of Dubai International Airport.pdfRising Above_ Dubai Floods and the Fortitude of Dubai International Airport.pdf
Rising Above_ Dubai Floods and the Fortitude of Dubai International Airport.pdf
 
2024: Domino Containers - The Next Step. News from the Domino Container commu...
2024: Domino Containers - The Next Step. News from the Domino Container commu...2024: Domino Containers - The Next Step. News from the Domino Container commu...
2024: Domino Containers - The Next Step. News from the Domino Container commu...
 
Spring Boot vs Quarkus the ultimate battle - DevoxxUK
Spring Boot vs Quarkus the ultimate battle - DevoxxUKSpring Boot vs Quarkus the ultimate battle - DevoxxUK
Spring Boot vs Quarkus the ultimate battle - DevoxxUK
 
ICT role in 21st century education and its challenges
ICT role in 21st century education and its challengesICT role in 21st century education and its challenges
ICT role in 21st century education and its challenges
 
CNIC Information System with Pakdata Cf In Pakistan
CNIC Information System with Pakdata Cf In PakistanCNIC Information System with Pakdata Cf In Pakistan
CNIC Information System with Pakdata Cf In Pakistan
 
Axa Assurance Maroc - Insurer Innovation Award 2024
Axa Assurance Maroc - Insurer Innovation Award 2024Axa Assurance Maroc - Insurer Innovation Award 2024
Axa Assurance Maroc - Insurer Innovation Award 2024
 
presentation ICT roal in 21st century education
presentation ICT roal in 21st century educationpresentation ICT roal in 21st century education
presentation ICT roal in 21st century education
 
Boost Fertility New Invention Ups Success Rates.pdf
Boost Fertility New Invention Ups Success Rates.pdfBoost Fertility New Invention Ups Success Rates.pdf
Boost Fertility New Invention Ups Success Rates.pdf
 
Cloud Frontiers: A Deep Dive into Serverless Spatial Data and FME
Cloud Frontiers:  A Deep Dive into Serverless Spatial Data and FMECloud Frontiers:  A Deep Dive into Serverless Spatial Data and FME
Cloud Frontiers: A Deep Dive into Serverless Spatial Data and FME
 
Connector Corner: Accelerate revenue generation using UiPath API-centric busi...
Connector Corner: Accelerate revenue generation using UiPath API-centric busi...Connector Corner: Accelerate revenue generation using UiPath API-centric busi...
Connector Corner: Accelerate revenue generation using UiPath API-centric busi...
 
Biography Of Angeliki Cooney | Senior Vice President Life Sciences | Albany, ...
Biography Of Angeliki Cooney | Senior Vice President Life Sciences | Albany, ...Biography Of Angeliki Cooney | Senior Vice President Life Sciences | Albany, ...
Biography Of Angeliki Cooney | Senior Vice President Life Sciences | Albany, ...
 
Modular Monolith - a Practical Alternative to Microservices @ Devoxx UK 2024
Modular Monolith - a Practical Alternative to Microservices @ Devoxx UK 2024Modular Monolith - a Practical Alternative to Microservices @ Devoxx UK 2024
Modular Monolith - a Practical Alternative to Microservices @ Devoxx UK 2024
 
Cloud Frontiers: A Deep Dive into Serverless Spatial Data and FME
Cloud Frontiers:  A Deep Dive into Serverless Spatial Data and FMECloud Frontiers:  A Deep Dive into Serverless Spatial Data and FME
Cloud Frontiers: A Deep Dive into Serverless Spatial Data and FME
 
+971581248768>> SAFE AND ORIGINAL ABORTION PILLS FOR SALE IN DUBAI AND ABUDHA...
+971581248768>> SAFE AND ORIGINAL ABORTION PILLS FOR SALE IN DUBAI AND ABUDHA...+971581248768>> SAFE AND ORIGINAL ABORTION PILLS FOR SALE IN DUBAI AND ABUDHA...
+971581248768>> SAFE AND ORIGINAL ABORTION PILLS FOR SALE IN DUBAI AND ABUDHA...
 

Writing Modular Command-line Apps with App::Cmd