Command::V2(3pm)

πŸ“¦
version 0.470 Β· 2 versions
, in debian bookworm, ubuntu jammy, ubuntu noble

πŸ’– Command πŸ’–

okay bestie, gather round 🫢 this page is Command β€” full name Command::V2, section 3pm, living in the User Contributed Perl Documentation set. And what is it? It's a base class for modules implementing the command pattern. That's the whole NAME line, no notes, periodt. πŸ’…


✨ SYNOPSIS ✨

use TopLevelNamespace;

class TopLevelNamespace::SomeObj::Command {
  is => 'Command',
  has => [
      someobj => { is => 'TopLevelNamespace::SomeObj', id_by => 'some_obj_id' },
      verbose => { is => 'Boolean', is_optional => 1 },
  ],
};

sub execute {
    my $self = shift;
    if ($self->verbose) {
        print "Working on id ",$self->some_obj_id,"\n";
    }
    my $result = $someobj->do_something();
    if ($self->verbose) {
        print "Result was $result\n";
    }
    return $result;
}

sub help_brief {
    return 'Call do_something on a SomeObj instance';
}
sub help_synopsis {
    return 'cmd --some_obj_id 123 --verbose';
}
sub help_detail {
    return 'This command performs a FooBarBaz transform on a SomObj object instance by calling its do_something method.';
}

# Another part of the code

my $cmd = TopLevelNamespace::SomeObj::Command->create(some_obj_id => $some_obj->id);
$cmd->execute();

🌸 DESCRIPTION 🌸

So the Command module is a base class for creating other command modules that implement the Command Pattern. Which is giving: these modules can be easily reused in applications, or loaded and executed dynamicaly in a command-line program. Both?? Yes bestie, both. πŸ”₯

Every Command subclass = one reusable work unit. And the bulk of the module's code is probably gonna live in the execute() method β€” that's the main character of your subclass, fr fr. execute() will usually take only a single argument, an instance of the Command subclass. Just the one. Simple. Iconic.


πŸŽ€ Command-line use πŸŽ€

Okay this part is so fun. If you make a top-level Command module called, like, TopLevelNamespace::Command, and a script called tln_cmd that looks like this:

#!/usr/bin/perl
use TopLevelNamespace;
TopLevelNamespace::Command->execute_with_shell_params_and_exit();

…then boom πŸ’₯ you have an instant command-line tool that acts as an interface to the whole hierarchy of command modules at TopLevelNamespace::Command. Instant. No cap.

For example:

> tln_cmd foo bar --baz 1 --qux

That will:

  • create an instance of TopLevelNamespace::Command::Foo::Bar (if that class exists, and only if, bestie πŸ™ˆ)
  • with params baz => 1 and qux => 1, assumming qux is a boolean property
  • call execute() on it
  • and translate the return value from execute() into the appropriate notion of a shell return value

And what does "appropriate notion" mean? It means if execute() returns true in the Perl sense, then the script returns 0 β€” true in the shell sense. Yes the truthiness flips, that's just the crossover episode we live in. πŸ¦‹

The infrastructure takes care of turning the command line parameters into parameters for create(). Params designated as is_optional are, of course, optional. And non-optional parameters that are missing will generate an error. As they should. πŸ’€

--help is an implicit param applicable to all Command modules. It generates some hopefully useful text based on the documentation in the class definition (the 'doc' attributes you can attach to a class and properties), plus the strings returned by help_detail(), help_brief() and help_synopsis(). So write those, bestie, your future self will thank you. πŸŽ€

⭐ TODO ⭐

Real talk: this documentation needs to be fleshed out more. There's a lot of special things you can do with Command modules that isn't mentioned here yet. So like… consider this the trailer, not the whole movie. πŸ‘‘


and that's the whole page, babe πŸ’œ β€” this one came from perl v5.32.1, dated 2022-01-17, and it's filed under Command::V2(3pm). go build some command modules, you're gonna eat πŸ“βœ¨

πŸ“¦ where this page comes from