前回構築した「Template Method × Strategy」のアーキテクチャ。今回はその真価を発揮させるため、新しい戦略 「圧縮バックアップ(tar.gz)」 を追加します。
既存のコード(Backup::Engine)を一切修正せずに機能追加できる体験こそが、オブジェクト指向設計の醍醐味です。
前回: 2パターンの協調動作 | 目次 | 次回: ログとエラーハンドリング
新しい要件:アーカイブを作りたい
これまでは「ディレクトリ構造を維持してコピー」していましたが、今度は「全ファイルを1つの backup.tar.gz にまとめたい」という要望が出たとします。
前回の設計で 「Strategy側でループを制御する(ファイルリストを受け取る)」 という選択をしたことが、ここで活きてきます。
実装:圧縮戦略
Perlでtarアーカイブを作るには Archive::Tar が標準的ですが、ここではインターフェースが使いやすい Archive::Tar::Wrapper やコマンド呼び出しなど色々選択肢があります。今回は標準モジュールの範囲で Archive::Tar を使ってみます(メモリ消費に注意が必要ですが、学習用として)。
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
| package Backup::Strategy::Archive;
use Moo;
use Archive::Tar;
use Path::Tiny;
with 'Backup::Strategy::Role';
has filename => (is => 'ro', default => 'backup.tar.gz');
sub execute {
my ($self, $engine, $files) = @_;
my $tar = Archive::Tar->new;
my $dest_file = $engine->dest_dir->child($self->filename);
print "Archiving " . scalar(@$files) . " files to $dest_file ...\n";
# Archive::Tarはメモリを使うので、大量ファイルの場合は
# Archive::Tar::Streamed や コマンド実行(system "tar ...")を検討すべきですが、
# ここではシンプルにadd_filesを使います
# add_filesにはパス文字列のリストが必要
my @path_strings = map { "$_" } @$files;
# 実際には相対パスで格納したいため、chdirするか、add_dataで工夫が必要。
# ここでは簡略化のため絶対パス追加後にrename...ではなく、
# シンプルにファイルを追加します。
$tar->add_files(@path_strings);
$tar->write($dest_file->stringify, COMPRESS_GZIP);
print "Created archive: " . $dest_file->stringify .
" (" . -s $dest_file . " bytes)\n";
}
1;
|
注: 実運用では Archive::Tar はファイル内容をメモリに読み込むため、巨大なファイルには向きません。実用的なツールにするなら system("tar -czf ...") を呼ぶ戦略クラスにするのが最も手軽で高速です。
利用コード
呼び出し側は、Strategyを差し替えるだけです。
1
2
3
4
5
6
7
8
9
10
11
| use Backup::Engine;
use Backup::Strategy::Archive;
# 戦略をArchiveに切り替え
my $engine = Backup::Engine->new(
source_dir => './src',
dest_dir => './backup_dir', # ここに tar.gz ができる
strategy => Backup::Strategy::Archive->new(filename => '2026-01-30.tar.gz'),
);
$engine->run;
|
実行結果
1
2
3
4
5
| Starting backup...
Scanning done. Found 1500 files.
Archiving 1500 files to ./backup_dir/2026-01-30.tar.gz ...
Created archive: ./backup_dir/2026-01-30.tar.gz (450320 bytes)
All done in 1.20 sec.
|
感動ポイント
Backup::Engine(メインロジック)のコードは 1行も変更していません。Backup::Strategy::Diff(差分コピーのロジック)など、他の戦略にも影響を与えていません。- 新しいファイル
Backup/Strategy/Archive.pm を置くだけで、機能が拡張されました。
これが 「Open-Closed Principle(開放閉鎖の原則)」 です。拡張に対しては開いており(Open)、修正に対しては閉じている(Closed)状態です。
次回は、このツールを本番環境でも安心して使えるように、ログ出力やエラーハンドリングといった「非機能要件」を強化していきます。