SlideShare una empresa de Scribd logo
1 de 155
Descargar para leer sin conexión
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!

Más contenido relacionado

La actualidad más candente

Fewer cables
Fewer cablesFewer cables
Fewer cablesacme
 
Any event intro
Any event introAny event intro
Any event introqiang
 
Keep it simple web development stack
Keep it simple web development stackKeep it simple web development stack
Keep it simple web development stackEric Ahn
 
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 PerlNova Patch
 
Asynchronous Programming FTW! 2 (with AnyEvent)
Asynchronous Programming FTW! 2 (with AnyEvent)Asynchronous Programming FTW! 2 (with AnyEvent)
Asynchronous Programming FTW! 2 (with AnyEvent)xSawyer
 
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 pluginsMarian Marinov
 
Perl web frameworks
Perl web frameworksPerl web frameworks
Perl web frameworksdiego_k
 
The promise of asynchronous php
The promise of asynchronous phpThe promise of asynchronous php
The promise of asynchronous phpWim Godden
 
Building Better Applications with Data::Manager
Building Better Applications with Data::ManagerBuilding Better Applications with Data::Manager
Building Better Applications with Data::ManagerJay Shirley
 
Smolder @Silex
Smolder @SilexSmolder @Silex
Smolder @SilexJeen Lee
 
My app is secure... I think
My app is secure... I thinkMy app is secure... I think
My app is secure... I thinkWim Godden
 
10 Catalyst Tips
10 Catalyst Tips10 Catalyst Tips
10 Catalyst TipsJay Shirley
 
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!Workhorse Computing
 
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 realtimeAndrea Cardinale
 
Teaching Your Machine To Find Fraudsters
Teaching Your Machine To Find FraudstersTeaching Your Machine To Find Fraudsters
Teaching Your Machine To Find FraudstersIan Barber
 
The promise of asynchronous php
The promise of asynchronous phpThe promise of asynchronous php
The promise of asynchronous phpWim Godden
 
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 VersionIan Barber
 

La actualidad más candente (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
 

Destacado

Windows command prompt a to z
Windows command prompt a to zWindows command prompt a to z
Windows command prompt a to zSubuh Kurniawan
 
cmd commands
cmd commandscmd commands
cmd commandsRAJ ANAND
 
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 ProgrammingStefan Marr
 
Fixing mobile phones
Fixing mobile phonesFixing mobile phones
Fixing mobile phonestheviolet
 
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 trickStefan Esser
 
Introduction to Processing and creative coding
Introduction to Processing and creative codingIntroduction to Processing and creative coding
Introduction to Processing and creative codingJerome Herr
 
Powershell
PowershellPowershell
PowershellUGAIA
 
Ensuring data integrity in pharmaceutical environment
Ensuring data integrity in pharmaceutical environmentEnsuring data integrity in pharmaceutical environment
Ensuring data integrity in pharmaceutical environmentdeepak mishra
 
Chapter 03 - Program Coding and Design
Chapter 03 - Program Coding and DesignChapter 03 - Program Coding and Design
Chapter 03 - Program Coding and Designpatf719
 
Junos vs ios Troubleshooting comands
Junos vs ios Troubleshooting comands Junos vs ios Troubleshooting comands
Junos vs ios Troubleshooting comands sandeep kumar
 
Pharma data integrity
Pharma data integrityPharma data integrity
Pharma data integrityGirish Swami
 
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
 

Destacado (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)
 

Similar a Writing Modular Command-line Apps with App::Cmd

Perl.Hacks.On.Vim
Perl.Hacks.On.VimPerl.Hacks.On.Vim
Perl.Hacks.On.VimLin Yo-An
 
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 ScottO'Reilly Media
 
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?Christophe Porteneuve
 
Good Evils In Perl
Good Evils In PerlGood Evils In Perl
Good Evils In PerlKang-min Liu
 
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.Workhorse Computing
 
The Dom Scripting Toolkit J Query
The Dom Scripting Toolkit J QueryThe Dom Scripting Toolkit J Query
The Dom Scripting Toolkit J QueryQConLondon2008
 
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 SauceJesse 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
 
Crafting Custom Interfaces with Sub::Exporter
Crafting Custom Interfaces with Sub::ExporterCrafting Custom Interfaces with Sub::Exporter
Crafting Custom Interfaces with Sub::ExporterRicardo Signes
 
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 it2shortplanks
 
Barely Legal Xxx Perl Presentation
Barely Legal Xxx Perl PresentationBarely Legal Xxx Perl Presentation
Barely Legal Xxx Perl PresentationAttila 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 jQuerydeimos
 
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? :PLuciano Rocha
 
R57php 1231677414471772-2
R57php 1231677414471772-2R57php 1231677414471772-2
R57php 1231677414471772-2ady36
 

Similar a 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
 

Más 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 ChristmasRicardo Signes
 
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.16Ricardo Signes
 
Perl 5.14 for Pragmatists
Perl 5.14 for PragmatistsPerl 5.14 for Pragmatists
Perl 5.14 for PragmatistsRicardo 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 DistributionsRicardo Signes
 
Perl 5.12 for Everyday Use
Perl 5.12 for Everyday UsePerl 5.12 for Everyday Use
Perl 5.12 for Everyday UseRicardo 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 FundamentalsRicardo Signes
 
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 InsaneRicardo Signes
 
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!!Ricardo Signes
 

Más 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!!
 

Último

Scaling API-first – The story of a global engineering organization
Scaling API-first – The story of a global engineering organizationScaling API-first – The story of a global engineering organization
Scaling API-first – The story of a global engineering organizationRadu Cotescu
 
08448380779 Call Girls In Diplomatic Enclave Women Seeking Men
08448380779 Call Girls In Diplomatic Enclave Women Seeking Men08448380779 Call Girls In Diplomatic Enclave Women Seeking Men
08448380779 Call Girls In Diplomatic Enclave Women Seeking MenDelhi Call girls
 
Transforming Data Streams with Kafka Connect: An Introduction to Single Messa...
Transforming Data Streams with Kafka Connect: An Introduction to Single Messa...Transforming Data Streams with Kafka Connect: An Introduction to Single Messa...
Transforming Data Streams with Kafka Connect: An Introduction to Single Messa...HostedbyConfluent
 
Mastering MySQL Database Architecture: Deep Dive into MySQL Shell and MySQL R...
Mastering MySQL Database Architecture: Deep Dive into MySQL Shell and MySQL R...Mastering MySQL Database Architecture: Deep Dive into MySQL Shell and MySQL R...
Mastering MySQL Database Architecture: Deep Dive into MySQL Shell and MySQL R...Miguel Araújo
 
04-2024-HHUG-Sales-and-Marketing-Alignment.pptx
04-2024-HHUG-Sales-and-Marketing-Alignment.pptx04-2024-HHUG-Sales-and-Marketing-Alignment.pptx
04-2024-HHUG-Sales-and-Marketing-Alignment.pptxHampshireHUG
 
The Codex of Business Writing Software for Real-World Solutions 2.pptx
The Codex of Business Writing Software for Real-World Solutions 2.pptxThe Codex of Business Writing Software for Real-World Solutions 2.pptx
The Codex of Business Writing Software for Real-World Solutions 2.pptxMalak Abu Hammad
 
The 7 Things I Know About Cyber Security After 25 Years | April 2024
The 7 Things I Know About Cyber Security After 25 Years | April 2024The 7 Things I Know About Cyber Security After 25 Years | April 2024
The 7 Things I Know About Cyber Security After 25 Years | April 2024Rafal Los
 
My Hashitalk Indonesia April 2024 Presentation
My Hashitalk Indonesia April 2024 PresentationMy Hashitalk Indonesia April 2024 Presentation
My Hashitalk Indonesia April 2024 PresentationRidwan Fadjar
 
08448380779 Call Girls In Greater Kailash - I Women Seeking Men
08448380779 Call Girls In Greater Kailash - I Women Seeking Men08448380779 Call Girls In Greater Kailash - I Women Seeking Men
08448380779 Call Girls In Greater Kailash - I Women Seeking MenDelhi Call girls
 
Strategies for Unlocking Knowledge Management in Microsoft 365 in the Copilot...
Strategies for Unlocking Knowledge Management in Microsoft 365 in the Copilot...Strategies for Unlocking Knowledge Management in Microsoft 365 in the Copilot...
Strategies for Unlocking Knowledge Management in Microsoft 365 in the Copilot...Drew Madelung
 
Slack Application Development 101 Slides
Slack Application Development 101 SlidesSlack Application Development 101 Slides
Slack Application Development 101 Slidespraypatel2
 
#StandardsGoals for 2024: What’s new for BISAC - Tech Forum 2024
#StandardsGoals for 2024: What’s new for BISAC - Tech Forum 2024#StandardsGoals for 2024: What’s new for BISAC - Tech Forum 2024
#StandardsGoals for 2024: What’s new for BISAC - Tech Forum 2024BookNet Canada
 
The Role of Taxonomy and Ontology in Semantic Layers - Heather Hedden.pdf
The Role of Taxonomy and Ontology in Semantic Layers - Heather Hedden.pdfThe Role of Taxonomy and Ontology in Semantic Layers - Heather Hedden.pdf
The Role of Taxonomy and Ontology in Semantic Layers - Heather Hedden.pdfEnterprise Knowledge
 
08448380779 Call Girls In Friends Colony Women Seeking Men
08448380779 Call Girls In Friends Colony Women Seeking Men08448380779 Call Girls In Friends Colony Women Seeking Men
08448380779 Call Girls In Friends Colony Women Seeking MenDelhi Call girls
 
How to convert PDF to text with Nanonets
How to convert PDF to text with NanonetsHow to convert PDF to text with Nanonets
How to convert PDF to text with Nanonetsnaman860154
 
Automating Business Process via MuleSoft Composer | Bangalore MuleSoft Meetup...
Automating Business Process via MuleSoft Composer | Bangalore MuleSoft Meetup...Automating Business Process via MuleSoft Composer | Bangalore MuleSoft Meetup...
Automating Business Process via MuleSoft Composer | Bangalore MuleSoft Meetup...shyamraj55
 
[2024]Digital Global Overview Report 2024 Meltwater.pdf
[2024]Digital Global Overview Report 2024 Meltwater.pdf[2024]Digital Global Overview Report 2024 Meltwater.pdf
[2024]Digital Global Overview Report 2024 Meltwater.pdfhans926745
 
Kalyanpur ) Call Girls in Lucknow Finest Escorts Service 🍸 8923113531 🎰 Avail...
Kalyanpur ) Call Girls in Lucknow Finest Escorts Service 🍸 8923113531 🎰 Avail...Kalyanpur ) Call Girls in Lucknow Finest Escorts Service 🍸 8923113531 🎰 Avail...
Kalyanpur ) Call Girls in Lucknow Finest Escorts Service 🍸 8923113531 🎰 Avail...gurkirankumar98700
 
GenCyber Cyber Security Day Presentation
GenCyber Cyber Security Day PresentationGenCyber Cyber Security Day Presentation
GenCyber Cyber Security Day PresentationMichael W. Hawkins
 
IAC 2024 - IA Fast Track to Search Focused AI Solutions
IAC 2024 - IA Fast Track to Search Focused AI SolutionsIAC 2024 - IA Fast Track to Search Focused AI Solutions
IAC 2024 - IA Fast Track to Search Focused AI SolutionsEnterprise Knowledge
 

Último (20)

Scaling API-first – The story of a global engineering organization
Scaling API-first – The story of a global engineering organizationScaling API-first – The story of a global engineering organization
Scaling API-first – The story of a global engineering organization
 
08448380779 Call Girls In Diplomatic Enclave Women Seeking Men
08448380779 Call Girls In Diplomatic Enclave Women Seeking Men08448380779 Call Girls In Diplomatic Enclave Women Seeking Men
08448380779 Call Girls In Diplomatic Enclave Women Seeking Men
 
Transforming Data Streams with Kafka Connect: An Introduction to Single Messa...
Transforming Data Streams with Kafka Connect: An Introduction to Single Messa...Transforming Data Streams with Kafka Connect: An Introduction to Single Messa...
Transforming Data Streams with Kafka Connect: An Introduction to Single Messa...
 
Mastering MySQL Database Architecture: Deep Dive into MySQL Shell and MySQL R...
Mastering MySQL Database Architecture: Deep Dive into MySQL Shell and MySQL R...Mastering MySQL Database Architecture: Deep Dive into MySQL Shell and MySQL R...
Mastering MySQL Database Architecture: Deep Dive into MySQL Shell and MySQL R...
 
04-2024-HHUG-Sales-and-Marketing-Alignment.pptx
04-2024-HHUG-Sales-and-Marketing-Alignment.pptx04-2024-HHUG-Sales-and-Marketing-Alignment.pptx
04-2024-HHUG-Sales-and-Marketing-Alignment.pptx
 
The Codex of Business Writing Software for Real-World Solutions 2.pptx
The Codex of Business Writing Software for Real-World Solutions 2.pptxThe Codex of Business Writing Software for Real-World Solutions 2.pptx
The Codex of Business Writing Software for Real-World Solutions 2.pptx
 
The 7 Things I Know About Cyber Security After 25 Years | April 2024
The 7 Things I Know About Cyber Security After 25 Years | April 2024The 7 Things I Know About Cyber Security After 25 Years | April 2024
The 7 Things I Know About Cyber Security After 25 Years | April 2024
 
My Hashitalk Indonesia April 2024 Presentation
My Hashitalk Indonesia April 2024 PresentationMy Hashitalk Indonesia April 2024 Presentation
My Hashitalk Indonesia April 2024 Presentation
 
08448380779 Call Girls In Greater Kailash - I Women Seeking Men
08448380779 Call Girls In Greater Kailash - I Women Seeking Men08448380779 Call Girls In Greater Kailash - I Women Seeking Men
08448380779 Call Girls In Greater Kailash - I Women Seeking Men
 
Strategies for Unlocking Knowledge Management in Microsoft 365 in the Copilot...
Strategies for Unlocking Knowledge Management in Microsoft 365 in the Copilot...Strategies for Unlocking Knowledge Management in Microsoft 365 in the Copilot...
Strategies for Unlocking Knowledge Management in Microsoft 365 in the Copilot...
 
Slack Application Development 101 Slides
Slack Application Development 101 SlidesSlack Application Development 101 Slides
Slack Application Development 101 Slides
 
#StandardsGoals for 2024: What’s new for BISAC - Tech Forum 2024
#StandardsGoals for 2024: What’s new for BISAC - Tech Forum 2024#StandardsGoals for 2024: What’s new for BISAC - Tech Forum 2024
#StandardsGoals for 2024: What’s new for BISAC - Tech Forum 2024
 
The Role of Taxonomy and Ontology in Semantic Layers - Heather Hedden.pdf
The Role of Taxonomy and Ontology in Semantic Layers - Heather Hedden.pdfThe Role of Taxonomy and Ontology in Semantic Layers - Heather Hedden.pdf
The Role of Taxonomy and Ontology in Semantic Layers - Heather Hedden.pdf
 
08448380779 Call Girls In Friends Colony Women Seeking Men
08448380779 Call Girls In Friends Colony Women Seeking Men08448380779 Call Girls In Friends Colony Women Seeking Men
08448380779 Call Girls In Friends Colony Women Seeking Men
 
How to convert PDF to text with Nanonets
How to convert PDF to text with NanonetsHow to convert PDF to text with Nanonets
How to convert PDF to text with Nanonets
 
Automating Business Process via MuleSoft Composer | Bangalore MuleSoft Meetup...
Automating Business Process via MuleSoft Composer | Bangalore MuleSoft Meetup...Automating Business Process via MuleSoft Composer | Bangalore MuleSoft Meetup...
Automating Business Process via MuleSoft Composer | Bangalore MuleSoft Meetup...
 
[2024]Digital Global Overview Report 2024 Meltwater.pdf
[2024]Digital Global Overview Report 2024 Meltwater.pdf[2024]Digital Global Overview Report 2024 Meltwater.pdf
[2024]Digital Global Overview Report 2024 Meltwater.pdf
 
Kalyanpur ) Call Girls in Lucknow Finest Escorts Service 🍸 8923113531 🎰 Avail...
Kalyanpur ) Call Girls in Lucknow Finest Escorts Service 🍸 8923113531 🎰 Avail...Kalyanpur ) Call Girls in Lucknow Finest Escorts Service 🍸 8923113531 🎰 Avail...
Kalyanpur ) Call Girls in Lucknow Finest Escorts Service 🍸 8923113531 🎰 Avail...
 
GenCyber Cyber Security Day Presentation
GenCyber Cyber Security Day PresentationGenCyber Cyber Security Day Presentation
GenCyber Cyber Security Day Presentation
 
IAC 2024 - IA Fast Track to Search Focused AI Solutions
IAC 2024 - IA Fast Track to Search Focused AI SolutionsIAC 2024 - IA Fast Track to Search Focused AI Solutions
IAC 2024 - IA Fast Track to Search Focused AI Solutions
 

Writing Modular Command-line Apps with App::Cmd