本稿は,実務で使用しているRobocopyスクリプトにおいて,重複処理が羅列してある状態を繰返し(foreach)と配列を使用することで改善した事例について解説します。
Robocopyの対象ディレクトリ数が少なければあまり問題無いかもしれませんが,数が多いと保守性の観点でも問題となり得ます。
今回は実際の改善内容を解説するとともに,保守性の観点における問題点も併せて解説します。
前提知識
繰返し

同じ処理やコードを何度も実行する制御構造です。
同じ処理を長々と羅列する必要がなくなり,コードを簡素化することができます。
PowerShellでは,主に以下のやり方があります。
- for文
- foreach文
- while文
- ForEach-Object
配列

プログラミングにおける変数定義方法の一つです。
複数の値(変数)を1つの集合体として扱うことができます。
配列へ格納した値には要素番号が自動的に付与され,要素番号を指定することで値を取り出すことが可能です。
また,やり方によっては配列へ格納した順番に従って値を取り出すこともできます。
NAS(Network Attached Storage)

LANケーブル等を使って,ネットワーク(家庭内・社内LAN)に直接接続できるハードディスク(HDD)やSSDのことです。
プロジェクトで扱う共通的なファイルを格納したりと,ファイルを共有するうえでは非常に有用です。
イツキIPアドレスを割り振る必要があるよ!
環境
本番環境NASから検証環境NASへの日次バックアップ取得
本番環境のNASにあるデータを検証環境のNASへコピーして日次バックアップを取得しています。


コピーにはRobocopyスクリプトを使用しており,タスクスケジューラにて夜間に実行しています。
タスクスケジューラ登録方法は以下の記事をご参照ください。


(参考)スクリプト修正のきっかけ
スクリプト修正のきっかけは,本番環境NASの容量が検証環境NASの容量を超えたためです。
日次バックアップを取得できなくなったことでバックアップ対象ディレクトリを見直す方針となり,スクリプトの修正が必要となりました。
なお,Robocopyについては,以下の記事も併せてご確認ください。


実務での対応
改善前:同じ処理が複数行にわたって羅列してある
スクリプトを確認したところ,ディレクトリが違うだけの同じ処理が並んでいる状態となっていました。
※オプションが他にもいろいろあったり成否判定も実装してありましたが,説明の都合上省略しています。
|
1 2 3 |
Robocopy /MIR /R:3 /W:10 /LOG+:"Robolog.log" "\\HonbanNAS\common" "\\KenshoNAS\common" Robocopy /MIR /R:3 /W:10 /LOG+:"Robolog.log" "\\HonbanNAS\infra" "\\KenshoNAS\infla" Robocopy /MIR /R:3 /W:10 /LOG+:"Robolog.log" "\\HonbanNAS\app" "\\KenshoNAS\app" |
改善後:配列と繰返し(foreach)を使用して保守性向上
バックアップの除外ディレクトリ設定と併せて,配列と繰返しを使用して同じ処理の羅列を改善しました。
ついでに,本番環境NASと検証環境NASのUNCパスやログファイル名も変数(定数扱い)に代入することで,主処理をいじることなく変数の値修正のみで対処できるようにもしました。
|
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 |
# NAS(UNCパス) $NAS_PRD = "\\HonbanNAS" $NAS_STG = "\\kenshoNAS" # サブディレクトリ $DIR_SUB_CMN = "\common" $DIR_SUB_INF = "\infla" $DIR_SUB_APP = "\app" # 除外ディレクトリ $DIR_EXC = "\public" # ログファイル名 $LOG_RCP = "Robolog.log" # バックアップ対象ディレクトリの配列定義 $arrayDirSub = @(${DIR_SUB_CMN}, ${DIR_SUB_INF}, ${DIR_SUB_APP}) foreach ($dirSub in ${arrayDirSub}) { # Robocopy実行 Robocopy "${NAS_PRD}${dirSub}" "${NAS_STG}${dirSub}" ` /MIR /R:3 /W:10 /LOG+:${LOG_RCP} /XD "${NAS_PRD}${dirSub}${DIR_EXC}" } |
問題点整理
問題点:保守性が良くない
改善前のRobocopyスクリプトでは,ディレクトリが異なるだけでRobocopy自体は同じ処理が並んでいる状態となっています。
|
1 2 3 |
Robocopy /MIR /R:3 /W:10 /LOG+:"Robolog.log" "\\HonbanNAS\common" "\\KenshoNAS\common" Robocopy /MIR /R:3 /W:10 /LOG+:"Robolog.log" "\\HonbanNAS\infra" "\\KenshoNAS\infla" Robocopy /MIR /R:3 /W:10 /LOG+:"Robolog.log" "\\HonbanNAS\app" "\\KenshoNAS\app" |
つまり,修正時の影響範囲が広いということです。
今後も仮にオプションの見直しやディレクトリを変更するとなった際,改善前のままではコピペ等での修正箇所が多くなるという問題が生じます。
ディレクトリ数が少なければあまり問題とならないかもしれませんが,修正漏れによる障害発生のリスクが高いことに変わりはありません。
改善効果:修正による障害発生リスクの最小化
ディレクトリの追加・削減対応が容易
配列の要素を修正するだけで良くなりました。
|
1 2 |
# バックアップ対象ディレクトリの配列定義 $arrayDirSub = @(${DIR_SUB_CMN}, ${DIR_SUB_INF}, ${DIR_SUB_APP}) |
修正誤りのリスク削減
同じ処理の羅列が無くなったことで修正箇所を最小限にでき,修正漏れ等の修正誤りによるリスクを削減することができました。
|
1 2 3 4 5 6 |
foreach ($dirSub in ${arrayDirSub}) { # Robocopy実行 Robocopy "${NAS_PRD}${dirSub}" "${NAS_STG}${dirSub}" ` /MIR /R:3 /W:10 /LOG+:${LOG_RCP} /XD "${NAS_PRD}${dirSub}${DIR_EXC}" } |
配列や繰返し(foreach等)を使用することで修正箇所を最小限にでき,障害発生リスクを最小限とすることが可能!
まとめ
単純に動かすだけであれば,実装方法はいくらでもあります。
結局のところ大切なのは目的(今回は日次バックアップ取得対象の変更)であり,今回のように同じ処理を羅列するのも,手段の一つとしては間違っていません。
しかし,保守性の観点(将来的な修正を見据えた実装)まで考えられれば,エンジニアとして一歩先に行けるかと思います。
ただ単に目的を達成するのではなく,先々のことも見据えて実装できるよう邁進する材料としていただけたら幸いです。



