Perl/Moose coding patterns, idioms, and anti-patterns for domain-driven projects.
Background knowledge for Perl/Moose projects. Auto-loaded for pattern guidance.
package MyApp::Domain::Entity;
use Moose;
use namespace::autoclean;
has 'id' => (is => 'ro', isa => 'Int', required => 1);
has 'name' => (is => 'rw', isa => 'Str', required => 1);
sub validate { my ($self) = @_; die "Empty name" unless length($self->name); 1 }
__PACKAGE__->meta->make_immutable;
1;
eval {}use Try::Tiny;
try { $repo->save($entity) }
catch { $logger->error("Save failed: $_"); die "Could not save: $_" };
| Pattern | Wrong | Correct |
|---------|-------|---------|
| Iterate | my @arr = @$ref; foreach (@arr) | foreach (@$ref) |
| Chunk | my @copy = @$ref; splice(...) | @{$ref}[$i..$end] |
| Return | return @array | return \@array |
| Pass | func(@array) | func(\@array) |
Domain (pure logic) -> Repository (data access) -> Mapper (transform) -> Controller (HTTP)
# WITH InflateColumn::DateTime in schema
$rs->create({ date_field => DateTime->now });
# WITHOUT InflateColumn::DateTime
use MyApp::Util::DateTime qw(formatOracleDateTime);
$rs->create({ date_field => formatOracleDateTime(DateTime->now) });
Never use string-returning now() functions for database fields.
eval {} without Try::Tiny -- loses error contextSearch for places (restaurants, cafes, etc.) via Google Places API proxy on localhost.
Interact with GitHub using the `gh` CLI. Use `gh issue`, `gh pr`, `gh run`, and `gh api` for issues, PRs, CI runs, and advanced queries.
Create or update AgentSkills. Use when designing, structuring, or packaging skills with scripts, references, and assets.
Start voice calls via the OpenClaw voice-call plugin.
Notion API for creating and managing pages, databases, and blocks.
Gemini CLI for one-shot Q&A, summaries, and generation.
Category:developer