用 Codex 或 Claude 帮你安装 复制这段 Prompt,粘贴到 Codex、Claude 或其他助手里,让它检查 Skill 页面并帮你完成安装。
直接命令不会经过审查 Prompt;运行前请先检查来源。
npx skills add https://github.com/SAM42-Lab/everything-claude-code-kr --skill perl-patterns命令会保持在同一行。复制前请横向滚动并检查完整内容。
想先保存到本地?可下载 SkillsMP 当前能够提供的文件。
캡처, 진단, 억제된 복구 및 인트로스펙션 보고서를 사용하여 AI 에이전트 실패에 대한 구조화된 셀프 디버깅 워크플로우를 수행합니다.
기술, 명령어, 규칙, 훅 및 기타 요소를 DAILY 대 LIBRARY 버킷으로 분류하여 특정 저장소에 대한 증거 기반의 ECC 설치 계획을 수립합니다. 전체 번들을 로드하는 대신 프로젝트에 실제로 필요한 것만 ECC를 트리밍해야 할 때 사용하세요.
리소스 명명, 상태 코드, 페이지네이션, 필터링, 에러 응답, 버전 관리 및 프로덕션 API를 위한 속도 제한을 포함한 REST API 설계 패턴.
基于 SOC 职业分类
正在显示 SKILL.md
| name | perl-patterns |
| description | 견고하고 유지보수가 쉬운 Perl 애플리케이션을 구축하기 위한 Modern Perl 5.36+ 관용구, 모범 사례 및 관례입니다. |
| origin | ECC |
견고하고 유지보수가 쉬운 애플리케이션을 구축하기 위한 관용적인 Perl 5.36+ 패턴 및 모범 사례입니다.
signatures, 명시적 모듈, 집중된 오류 처리 및 테스트 가능한 경계와 같은 Modern Perl 5.36+ 기본값을 지향하는 방향으로 이 패턴들을 적용합니다. 아래 예제들은 시작점으로 복사하여 사용할 수 있으며, 실제 애플리케이션, 의존성 스택 및 배포 모델에 맞게 조정하십시오.
v5.36 Pragma 사용단일 use v5.36 문구가 오래된 상형문자 같은 설정들을 대체하며 strict, warnings 및 서브루틴 signatures를 활성화합니다.
# 좋음: 현대적인 서문
use v5.36;
sub greet($name) {
say "Hello, $name!";
}
# 나쁨: 레거시 설정
use strict;
use warnings;
use feature 'say', 'signatures';
no warnings 'experimental::signatures';
sub greet {
my ($name) = @_;
say "Hello, $name!";
}
명확성과 자동 인수 개수 확인을 위해 signatures를 사용합니다.
use v5.36;
# 좋음: 기본값이 있는 Signatures
sub connect_db($host, $port = 5432, $timeout = 30) {
# $host는 필수이며, 나머지는 기본값이 있음
return DBI->connect("dbi:Pg:host=$host;port=$port", undef, undef, {
RaiseError => 1,
PrintError => 0,
});
}
# 좋음: 가변 인수를 위한 Slurpy 매개변수
sub log_message($level, @details) {
say "[$level] " . join(' ', @details);
}
# 나쁨: 수동 인구 해제(unpacking)
sub connect_db {
my ($host, $port, $timeout) = @_;
$port //= 5432;
$timeout //= 30;
# ...
}
Perl의 핵심 개념인 scalar vs list 컨텍스트를 이해하십시오.
use v5.36;
my @items = (1, 2, 3, 4, 5);
my @copy = @items; # List 컨텍스트: 모든 요소
my $count = @items; # Scalar 컨텍스트: 개수 (5)
say "Items: " . scalar @items; # Scalar 컨텍스트 강제
중첩된 구조에서 가독성을 위해 postfix dereference 구문을 사용합니다.
use v5.36;
my $data = {
users => [
{ name => 'Alice', roles => ['admin', 'user'] },
{ name => 'Bob', roles => ['user'] },
],
};
# 좋음: Postfix dereferencing
my @users = $data->{users}->@*;
my @roles = $data->{users}[0]{roles}->@*;
my %first = $data->{users}[0]->%*;
# 나쁨: Circumfix dereferencing (체이닝 시 읽기 어려움)
my @users = @{ $data->{users} };
my @roles = @{ $data->{users}[0]{roles} };
isa 연산자 (5.32+)중치(Infix) 타입 확인 — blessed($o) && $o->isa('X')를 대체합니다.
use v5.36;
if ($obj isa 'My::Class') { $obj->do_something }
use v5.36;
sub parse_config($path) {
my $content = eval { path($path)->slurp_utf8 };
die "Config error: $@" if $@;
return decode_json($content);
}
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;
}
use v5.40;
sub divide($x, $y) {
try {
die "Division by zero" if $y == 0;
return $x / $y;
}
catch ($e) {
warn "Error: $e";
return;
}
}
가볍고 현대적인 OO를 위해 Moo를 선호하십시오. 메타프로토콜이 필요한 경우에만 Moose를 사용합니다.
# 좋음: 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',
,
[, ],
);
User;
{
(, ) = ;
\, ;
}
{ []->{name} }
;
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;
# 좋음: 가독성을 위해 /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}";
}
# 나쁨: 위치 기반 캡처 (유지보수 어려움)
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;
# 좋음: 한 번 컴파일하고 여러 번 사용
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;
# Hash 및 array 레퍼런스
my $config = {
database => {
host => 'localhost',
port => 5432,
options => ['utf8', 'sslmode=require'],
},
};
# 안전한 깊은 접근 (계층이 없으면 undef 반환)
my $port = $config->{database}{port}; # 5432
my $missing = $config->{cache}{host}; # undef, 오류 없음
# Hash 슬라이스
my %subset;
@subset{qw(host port)} = @{$config->{database}}{qw(host port)};
# Array 슬라이스
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";
}
use v5.36;
# 좋음: 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;
}
# 나쁨: 2개 인수 open (셸 인젝션 위험, perl-security 참조)
open FH, $path; # 절대 하지 마십시오
open FH, "< $path"; # 여전히 나쁨 — 모드 문자열에 사용자 데이터 포함
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;
-i=4 # 4칸 들여쓰기
-l=100 # 100자 라인 길이
-ci=4 # 연속 들여쓰기
-ce # else를 닫는 중괄호와 같은 줄에 (cuddled else)
-bar # 여는 중괄호를 같은 줄에
-nolq # 긴 인용 문자열을 내어쓰지 않음
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
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';
};
| 레거시 패턴 | 현대적 대체 |
|---|---|
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/catch (5.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); # 나쁨
my $obj = Foo->new(bar => 1); # 좋음
# 3. $_에 과도한 의존
map { process($_) } grep { validate($_) } @items; # 따라가기 어려움
my @valid = grep { validate($_) } @items; # 나음: 분리하십시오
my @results = map { process($_) } @valid;
# 4. strict refs 비활성화
no strict 'refs'; # 거의 항상 잘못된 선택
${"My::Package::$var"} = $value; # 대신 해시를 사용하십시오
# 5. 설정을 위해 전역 변수 사용
our $TIMEOUT = 30; # 나쁨: 가변 전역 변수
use constant TIMEOUT => 30; # 나음: 상수
# 최선: 기본값이 있는 Moo 속성
# 6. 모듈 로딩을 위해 문자열 eval 사용
;
;
Module::Runtime ;
require_module();
기억하십시오: Modern Perl은 깔끔하고 가독성이 좋으며 안전합니다. use v5.36이 상형문자 같은 설정들을 처리하게 하고, 객체를 위해 Moo를 사용하며, 직접 만든 솔루션보다는 CPAN의 검증된 모듈을 선호하십시오.