Files
everything-claude-code/docs/ja-JP/skills/perl-patterns/SKILL.md
Claude ec9ace9c54 docs: add native Japanese translation of ECC documentation (ja-JP)
Translate everything-claude-code repository to Japanese including:
- 17 root documentation files
- 60 agent documentation files
- 80 command documentation files
- 99 rule files across 18 language directories (common, angular, arkts, cpp, csharp, dart, fsharp, golang, java, kotlin, perl, php, python, ruby, rust, swift, typescript, web)
- 199 skill documentation files

Total: 455 files translated to Japanese with:
- Consistent terminology glossary applied throughout
- YAML field names preserved in English (name, description, etc.)
- Code blocks and examples untouched (comments translated)
- Markdown structure and relative links preserved
- Professional translation maintaining technical accuracy

This translation expands ECC accessibility to Japanese-speaking developers and teams.

Co-Authored-By: Claude Haiku 4.5 <noreply@anthropic.com>
2026-05-17 02:31:40 -04:00

13 KiB
Raw Blame History

name, description, origin
name description origin
perl-patterns 堅牢でメンテナブルなPerlアプリケーションを構築するためのModern Perl 5.36+のイディオム、ベストプラクティス、規約。 ECC

モダンPerl開発パターン

堅牢でメンテナブルなアプリケーションを構築するためのイディオマティックなPerl 5.36+パターンとベストプラクティス。

アクティベートするタイミング

  • 新しいPerlコードまたはモジュールを書くとき
  • イディオム準拠のためにPerlコードをレビューするとき
  • レガシーPerlをモダンな標準にリファクタリングするとき
  • PerlモジュールのアーキテクチャをDesignするとき
  • 5.36以前のコードをモダンなPerlに移行するとき

仕組み

これらのパターンをModern Perl 5.36+のデフォルトへのバイアスとして適用する: シグネチャ、明示的なモジュール、集中的なエラー処理、テスト可能な境界。以下の例は出発点としてコピーし、目の前の実際のアプリ、依存スタック、デプロイモデルに合わせて締め付けることを意図している。

コア原則

1. v5.36プラグマの使用

単一のuse v5.36が古い定型文を置き換え、strict、warnings、サブルーチンシグネチャを有効化する。

# Good: モダンなプリアンブル
use v5.36;

sub greet($name) {
    say "Hello, $name!";
}

# Bad: レガシーな定型文
use strict;
use warnings;
use feature 'say', 'signatures';
no warnings 'experimental::signatures';

sub greet {
    my ($name) = @_;
    say "Hello, $name!";
}

2. サブルーチンシグネチャ

明確さと自動アリティチェックのためにシグネチャを使用する。

use v5.36;

# Good: デフォルト値付きシグネチャ
sub connect_db($host, $port = 5432, $timeout = 30) {
    # $hostは必須、その他はデフォルトあり
    return DBI->connect("dbi:Pg:host=$host;port=$port", undef, undef, {
        RaiseError => 1,
        PrintError => 0,
    });
}

# Good: 可変引数のためのスラーピーパラメータ
sub log_message($level, @details) {
    say "[$level] " . join(' ', @details);
}

# Bad: 手動引数アンパック
sub connect_db {
    my ($host, $port, $timeout) = @_;
    $port    //= 5432;
    $timeout //= 30;
    # ...
}

3. コンテキスト感度

スカラーvsリストコンテキストを理解する — Perlのコアコンセプト。

use v5.36;

my @items = (1, 2, 3, 4, 5);

my @copy  = @items;            # リストコンテキスト: すべての要素
my $count = @items;            # スカラーコンテキスト: カウント (5)
say "Items: " . scalar @items; # スカラーコンテキストを強制

4. 後置逆参照

ネストされた構造で読みやすさのために後置逆参照構文を使用する。

use v5.36;

my $data = {
    users => [
        { name => 'Alice', roles => ['admin', 'user'] },
        { name => 'Bob',   roles => ['user'] },
    ],
};

# Good: 後置逆参照
my @users = $data->{users}->@*;
my @roles = $data->{users}[0]{roles}->@*;
my %first = $data->{users}[0]->%*;

# Bad: 前置逆参照チェーンで読みにくい
my @users = @{ $data->{users} };
my @roles = @{ $data->{users}[0]{roles} };

5. isa演算子5.32+

中置型チェック — blessed($o) && $o->isa('X')を置き換える。

use v5.36;
if ($obj isa 'My::Class') { $obj->do_something }

エラー処理

eval/dieパターン

use v5.36;

sub parse_config($path) {
    my $content = eval { path($path)->slurp_utf8 };
    die "Config error: $@" if $@;
    return decode_json($content);
}

Try::Tiny信頼性の高い例外処理

use v5.36;
use Try::Tiny;

sub fetch_user($id) {
    my $user = try {
        $db->resultset('User')->find($id)
            // die "User $id not found\n";
    }
    catch {
        warn "Failed to fetch user $id: $_";
        undef;
    };
    return $user;
}

ネイティブtry/catch5.40+

use v5.40;

sub divide($x, $y) {
    try {
        die "Division by zero" if $y == 0;
        return $x / $y;
    }
    catch ($e) {
        warn "Error: $e";
        return;
    }
}

MooによるモダンOO

軽量でモダンなOOにはMooを優先する。メタプロトコルが必要な場合のみMooseを使用する。

# Good: Mooクラス
package User;
use Moo;
use Types::Standard qw(Str Int ArrayRef);
use namespace::autoclean;

has name  => (is => 'ro', isa => Str, required => 1);
has email => (is => 'ro', isa => Str, required => 1);
has age   => (is => 'ro', isa => Int, default  => sub { 0 });
has roles => (is => 'ro', isa => ArrayRef[Str], default => sub { [] });

sub is_admin($self) {
    return grep { $_ eq 'admin' } $self->roles->@*;
}

sub greet($self) {
    return "Hello, I'm " . $self->name;
}

1;

# 使用法
my $user = User->new(
    name  => 'Alice',
    email => 'alice@example.com',
    roles => ['admin', 'user'],
);

# Bad: ブレスされたhashrefバリデーションなし、アクセサなし
package User;
sub new {
    my ($class, %args) = @_;
    return bless \%args, $class;
}
sub name { return $_[0]->{name} }
1;

Mooロール

package Role::Serializable;
use Moo::Role;
use JSON::MaybeXS qw(encode_json);
requires 'TO_HASH';
sub to_json($self) { encode_json($self->TO_HASH) }
1;

package User;
use Moo;
with 'Role::Serializable';
has name  => (is => 'ro', required => 1);
has email => (is => 'ro', required => 1);
sub TO_HASH($self) { { name => $self->name, email => $self->email } }
1;

ネイティブclassキーワード5.38+、Corinna

use v5.38;
use feature 'class';
no warnings 'experimental::class';

class Point {
    field $x :param;
    field $y :param;
    method magnitude() { sqrt($x**2 + $y**2) }
}

my $p = Point->new(x => 3, y => 4);
say $p->magnitude;  # 5

正規表現

名前付きキャプチャと/xフラグ

use v5.36;

# Good: 読みやすさのための/xを使った名前付きキャプチャ
my $log_re = qr{
    ^ (?<timestamp> \d{4}-\d{2}-\d{2} \s \d{2}:\d{2}:\d{2} )
    \s+ \[ (?<level> \w+ ) \]
    \s+ (?<message> .+ ) $
}x;

if ($line =~ $log_re) {
    say "Time: $+{timestamp}, Level: $+{level}";
    say "Message: $+{message}";
}

# Bad: 位置キャプチャ(メンテが難しい)
if ($line =~ /^(\d{4}-\d{2}-\d{2} \d{2}:\d{2}:\d{2})\s+\[(\w+)\]\s+(.+)$/) {
    say "Time: $1, Level: $2";
}

プリコンパイルパターン

use v5.36;

# Good: 1回コンパイル、複数回使用
my $email_re = qr/^[A-Za-z0-9._%+-]+\@[A-Za-z0-9.-]+\.[A-Za-z]{2,}$/;

sub validate_emails(@emails) {
    return grep { $_ =~ $email_re } @emails;
}

データ構造

リファレンスと安全な深いアクセス

use v5.36;

# ハッシュと配列リファレンス
my $config = {
    database => {
        host => 'localhost',
        port => 5432,
        options => ['utf8', 'sslmode=require'],
    },
};

# 安全な深いアクセスどのレベルが欠落してもundefを返す
my $port = $config->{database}{port};           # 5432
my $missing = $config->{cache}{host};           # undef、エラーなし

# ハッシュスライス
my %subset;
@subset{qw(host port)} = @{$config->{database}}{qw(host port)};

# 配列スライス
my @first_two = $config->{database}{options}->@[0, 1];

# 複数変数のforループ5.36で実験的、5.40で安定)
use feature 'for_list';
no warnings 'experimental::for_list';
for my ($key, $val) (%$config) {
    say "$key => $val";
}

ファイルI/O

3引数open

use v5.36;

# Good: autodieを使った3引数openコアモジュール、'or die'を排除)
use autodie;

sub read_file($path) {
    open my $fh, '<:encoding(UTF-8)', $path;
    local $/;
    my $content = <$fh>;
    close $fh;
    return $content;
}

# Bad: 2引数openシェルインジェクションリスク、perl-securityを参照
open FH, $path;            # 絶対にしない
open FH, "< $path";        # まだ悪い — モード文字列のユーザーデータ

ファイル操作のPath::Tiny

use v5.36;
use Path::Tiny;

my $file = path('config', 'app.json');
my $content = $file->slurp_utf8;
$file->spew_utf8($new_content);

# ディレクトリを反復
for my $child (path('src')->children(qr/\.pl$/)) {
    say $child->basename;
}

モジュール構成

標準プロジェクトレイアウト

MyApp/
├── lib/
│   └── MyApp/
│       ├── App.pm           # メインモジュール
│       ├── Config.pm        # 設定
│       ├── DB.pm            # データベース層
│       └── Util.pm          # ユーティリティ
├── bin/
│   └── myapp                # エントリーポイントスクリプト
├── t/
│   ├── 00-load.t            # コンパイルテスト
│   ├── unit/                # ユニットテスト
│   └── integration/         # インテグレーションテスト
├── cpanfile                 # 依存関係
├── Makefile.PL              # ビルドシステム
└── .perlcriticrc            # リンティング設定

エクスポーターパターン

package MyApp::Util;
use v5.36;
use Exporter 'import';

our @EXPORT_OK   = qw(trim);
our %EXPORT_TAGS = (all => \@EXPORT_OK);

sub trim($str) { $str =~ s/^\s+|\s+$//gr }

1;

ツーリング

perltidy設定.perltidyrc

-i=4        # 4スペースインデント
-l=100      # 100文字行長
-ci=4       # 継続インデント
-ce         # cuddled else
-bar        # 同じ行に開き括弧
-nolq       # 長い引用文字列のアウトデントをしない

perlcritic設定.perlcriticrc

severity = 3
theme = core + pbp + security

[InputOutput::RequireCheckedSyscalls]
functions = :builtins
exclude_functions = say print

[Subroutines::ProhibitExplicitReturnUndef]
severity = 4

[ValuesAndExpressions::ProhibitMagicNumbers]
allowed_values = 0 1 2 -1

依存関係管理cpanfile + carton

cpanm App::cpanminus Carton   # ツールをインストール
carton install                 # cpanfileから依存関係をインストール
carton exec -- perl bin/myapp  # ローカル依存関係で実行
# cpanfile
requires 'Moo', '>= 2.005';
requires 'Path::Tiny';
requires 'JSON::MaybeXS';
requires 'Try::Tiny';

on test => sub {
    requires 'Test2::V0';
    requires 'Test::MockModule';
};

クイックリファレンス: モダンPerlイディオム

レガシーパターン モダンな置き換え
use strict; use warnings; use v5.36;
my ($x, $y) = @_; sub foo($x, $y) { ... }
@{ $ref } $ref->@*
%{ $ref } $ref->%*
open FH, "< $file" open my $fh, '<:encoding(UTF-8)', $file
blessed hashref 型付きのMooクラス
$1, $2, $3 $+{name}(名前付きキャプチャ)
eval { }; if ($@) Try::Tinyまたはネイティブtry/catch5.40+
BEGIN { require Exporter; } use Exporter 'import';
手動ファイル操作 Path::Tiny
blessed($o) && $o->isa('X') $o isa 'X'5.32+
builtin::true / false use builtin 'true', 'false';5.36+、実験的)

アンチパターン

# 1. 2引数openセキュリティリスク
open FH, $filename;                     # 絶対にしない

# 2. 間接オブジェクト構文(あいまいな解析)
my $obj = new Foo(bar => 1);            # Bad
my $obj = Foo->new(bar => 1);           # Good

# 3. $_への過度の依存
map { process($_) } grep { validate($_) } @items;  # 追うのが難しい
my @valid = grep { validate($_) } @items;           # より良い: 分割する
my @results = map { process($_) } @valid;

# 4. strictリファレンスの無効化
no strict 'refs';                        # ほぼ常に間違い
${"My::Package::$var"} = $value;         # 代わりにhashを使用

# 5. グローバル変数を設定として使用
our $TIMEOUT = 30;                       # Bad: 可変グローバル
use constant TIMEOUT => 30;              # Better: 定数
# Best: デフォルト付きのMoo属性

# 6. モジュールロードのための文字列eval
eval "require $module";                  # Bad: コードインジェクションリスク
eval "use $module";                      # Bad
use Module::Runtime 'require_module';    # Good: 安全なモジュールロード
require_module($module);

忘れないこと: モダンなPerlはクリーン、読みやすく、安全である。use v5.36に定型文を処理させ、オブジェクトにはMooを使用し、手作りのソリューションよりCPANの実績あるモジュールを優先する。