Kubernetes-REST

 view release on metacpan or  search on metacpan

.claude/skills/perl-moo/SKILL.md  view on Meta::CPAN

## Pattern 1 – `extends` + Attribute Override

```perl
package App::Base;
use Moo;
has prefix => (is => 'ro', default => sub { 'Hello' });
sub greet { $_[0]->prefix . ", " . $_[0]->name }

package App::Friendly;
use Moo;
extends 'App::Base';
has '+prefix' => (default => sub { 'Hi' });   # override via +attr
```

**Rules:** Multiple `extends` calls REPLACE (don't add). Reference defaults always as coderefs (`sub { [] }`, never `[]`).

---

## Pattern 2 – Role with `requires`

```perl
package App::Role::UppercaseName;
use Moo::Role;
requires 'name';                          # contract: consumer must have name()
sub uppercase_name { uc $_[0]->name }

package App::User;
use Moo;
extends 'App::Base';
with 'App::Role::UppercaseName';          # composed; missing 'name' → loud failure
```

**Rules:** `requires` fails at composition time, not runtime. Imports inside a role land as methods on the consumer unless cleaned up – everything loaded *before* `use Moo::Role` is auto-cleaned; everything after is composed.

---

## Pattern 3 – Thin Classes (roles only, no base)

```perl
package App::Role::HasId;  use Moo::Role; has id => (is => 'ro', required => 1);
package App::Role::CanDescribe;
use Moo::Role; requires 'id';
sub describe { "id=" . $_[0]->id }

package App::Thing;
use Moo;
with 'App::Role::HasId', 'App::Role::CanDescribe';
```

Use when there's no meaningful "is-a" relationship. Prefer over deep hierarchies.

---

## Pattern 4 – House-Style Import Module

```perl
package My::Mooish;
use Import::Into;
sub import {
    my $target = caller;
    strict->import::into($target);
    warnings->import::into($target);
    Moo->import::into($target);
    namespace::clean->import::into($target);   # after Moo, cleans stray imports
}

package App::Thing;
use My::Mooish;
has x => (is => 'ro', default => sub { 1 });
```

**Rules:** Order matters: imports → `use Moo` → `namespace::clean`. Use `namespace::autoclean` ≥ 0.16 only (older versions inflate Moo classes to Moose). Use `strictures` v2 with Moo 2.

---

## Pattern 5 – Delegation via `handles`

```perl
package App::UsesCounter;
use Moo;
has counter => (
    is      => 'ro',
    required => 1,
    handles => 'App::Role::CounterAPI',   # role defines the interface (inc/reset/value)
);
```

Three forms: `handles => 'RoleName'` (interface from role), `handles => [qw(inc reset)]` (list), `handles => { add => 'push' }` (rename). Does not trigger `isa`/`coerce`/`trigger` on the delegate itself.

---

## Pattern 6 – Native-Trait Delegation via `Sub::HandlesVia`

```perl
package Kitchen;
use Moo;
use Sub::HandlesVia;
use Types::Standard qw(ArrayRef Str);
has food => (
    is          => 'ro',
    isa         => ArrayRef[Str],
    handles_via => 'Array',
    default     => sub { [] },
    handles     => { add => 'push', find => 'grep' },
);
```

**Use `Sub::HandlesVia` over `MooX::HandlesVia`** – the latter documents that triggers/coercions don't fire on delegated mutations. Load `Sub::HandlesVia` *after* `use Moo`.

---

## Pattern 7 – Method Modifiers

```perl
before calc => sub { die "x<0" if $_[1] < 0 };         # validate, can't change return

around calc => sub {
    my ($orig, $self, $x) = @_;
    return $self->$orig($x) + 1;                        # can change return value
};



( run in 3.121 seconds using v1.01-cache-2.11-cpan-5a3173703d6 )