Created
October 6, 2018 05:58
-
-
Save nimzo6689/9bba84c4a01c5e65825286a57535721c to your computer and use it in GitHub Desktop.
Qiita用「PowerShellでもっといい条件文の書き方5選」
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Set-StrictMode -Version 2.0 | |
##### 1. 包含演算子で論理演算子の数を減らす ################### | |
function Test01_Bad($fruit) { | |
# リンゴ、イチゴ、サクランボであれば赤と判定する。 | |
if ($fruit -eq 'リンゴ' -or $fruit -eq 'イチゴ' -or $fruit -eq 'サクランボ') { | |
return '赤' | |
} | |
} | |
function Test01_Good($fruit) { | |
# リンゴ、イチゴ、サクランボであれば赤と判定する。 | |
if ($fruit -in @('リンゴ', 'イチゴ', 'サクランボ')) { | |
return '赤' | |
} | |
} | |
##### 2. Avoid Else, Return Early の掟に従う ################### | |
function Test02_Bad($fruit, $quantity) { | |
$redFruits = @('リンゴ', 'イチゴ', 'サクランボ', 'クランベリー') | |
# 条件1: $fruitに何かしらの文字列が入っていること。 | |
if ($fruit) { | |
# 条件2: 赤い果物を抽出 | |
if ($redFruits | Where-Object {$_ -in $fruit}) { | |
# 条件3: 量が一定数より多いこと | |
if ($quantity -gt 10) { | |
return '量が多い' | |
} | |
} | |
} | |
else { | |
throw '果物が指定されていません' | |
} | |
} | |
function Test02_Good($fruit, $quantity) { | |
$redFruits = @('リンゴ', 'イチゴ', 'サクランボ', 'クランベリー') | |
# 条件1: エラーを早期にthrowします | |
if (!$fruit) { | |
throw '果物が指定されていません' | |
} | |
# 条件2: 赤い果実を抽出 | |
if ($redFruits | Where-Object {$_ -in $fruit}) { | |
# 条件3: 量が一定数より多いこと | |
if ($quantity -gt 10) { | |
return '量が多い' | |
} | |
} | |
} | |
function Test02_OverdoReturnEarly($fruit, $quantity) { | |
$redFruits = @('リンゴ', 'イチゴ', 'サクランボ', 'クランベリー') | |
if (!$fruit) { | |
# 条件1: エラーを早期にthrowします | |
throw '果物が指定されていません' | |
} | |
if (!($redFruits | Where-Object {$_ -in $fruit})) { | |
# 条件2: 赤い果物でなければ処理を中断します | |
return | |
} | |
# 条件3: 量が一定数より多いこと | |
if ($quantity -gt 10) { | |
return '量が多い' | |
} | |
} | |
##### 3. 引数の検査処理は関数の機能でなくす ################### | |
function Test03_Bad($fruit, $quantity) { | |
if (!$fruit) { | |
throw '果物が指定されていません' | |
} | |
$quantity = if ($quantity) { | |
$quantity | |
} | |
else { | |
1 | |
} | |
return "${quantity}個の${fruit}があります!" | |
} | |
function Test03_Good($fruit, $quantity = 1) { | |
if (!$fruit) { | |
throw '果物が指定されていません' | |
} | |
return "${quantity}個の${fruit}があります!" | |
} | |
function Test03_Good_Advanced { | |
param( | |
[Parameter(Mandatory)] | |
[ValidateNotNull()] | |
$fruit, | |
$quantity = 1 | |
) | |
return "${quantity}個の${fruit}があります!" | |
} | |
##### 4. switch文よりHashTableが単純でよい ################### | |
function Test04_Bad($color) { | |
# 色に該当する果物をswitch文で判定 | |
switch ($color) { | |
'赤' { | |
return @('リンゴ', 'イチゴ') | |
} | |
'黄' { | |
return @('バナナ', 'パイナップル') | |
} | |
'紫' { | |
return @('ブドウ', 'ブルーベリー') | |
} | |
default { | |
return @() | |
} | |
} | |
} | |
function Test04_Good($color) { | |
# 色に該当する果物をHashTableで判定 | |
$fruitColors = @{ | |
"赤" = @('リンゴ', 'イチゴ') | |
"黄" = @('バナナ', 'パイナップル') | |
"紫" = @('ブドウ', 'ブルーベリー') | |
} | |
if ($color -in $fruitColors.Keys) { | |
return $fruitColors[$color] | |
} | |
return @() | |
} | |
# 補足:スプラッティング(HashTableを使った実引数の指定方法)について | |
function Test04_Splatting($hoge, $fuga, $piyo, $hogera, $hogehoge, $fugafuga, $piyopiyo, $hogerahogera) { | |
$diff = Compare-Object -IncludeEqual @( | |
$hoge, $fuga, $piyo, $hogera, $hogehoge, $fugafuga, $piyopiyo, $hogerahogera | |
) @( | |
'hoge', 'fuga', 'piyo', 'hogera', 'hogehoge', 'fugafuga', 'piyopiyo', 'hogerahogera' | |
) | |
$diff.SideIndicator -notcontains '=>' | |
} | |
function Test04_SplattingDemo() { | |
$splatting = @{ | |
hoge = 'hoge'; fuga = 'fuga'; piyo = 'piyo'; hogera = 'hogera' | |
hogehoge = 'hogehoge'; fugafuga = 'fugafuga'; piyopiyo = 'piyopiyo'; hogerahogera = 'hogerahogera' | |
} | |
Test04_Splatting @splatting | |
#=> True | |
} | |
function Test04_SplattingPramName() { | |
Test04_Splatting ` | |
-hoge 'hoge' -fuga 'fuga' -piyo 'piyo' -hogera 'hogera' ` | |
-hogehoge 'hogehoge' -fugafuga 'fugafuga' -piyopiyo 'piyopiyo' -hogerahogera 'hogerahogera' | |
#=> True | |
} | |
##### 5. ANY は -in 、ALLはForEach-Objectを上手く使う ################### | |
function Test05_Bad_Any($fruits) { | |
$color = '赤' | |
$isAllRed = $false | |
# 条件: 一つ以上の果物が赤色であること | |
foreach ($fruit in $fruits) { | |
if ($isAllRed) { | |
break; | |
} | |
$isAllRed = $fruit.color -eq $color | |
} | |
return $isAllRed | |
} | |
$fruitsAnyRed = @( | |
@{name = 'リンゴ'; color = '赤'}, | |
@{name = 'バナナ'; color = '黄'}, | |
@{name = 'ブドウ'; color = '紫'} | |
) | |
$fruitsExceptRed = @( | |
@{name = 'バナナ'; color = '黄'}, | |
@{name = 'ブドウ'; color = '紫'}, | |
@{name = 'メロン'; color = '緑'} | |
) | |
function Test05_Good_Any($fruits) { | |
$color = '赤' | |
# 条件: 一つ以上の果物が赤色であること(簡潔版) | |
$color -in $fruits.color | |
} | |
function Test05_Bad_Every($fruits) { | |
$color = '赤' | |
$isAllRed = $true | |
# 条件: すべての果物が赤色であること | |
foreach ($fruit in $fruits) { | |
if (!$isAllRed) { | |
break; | |
} | |
$isAllRed = $fruit.color -eq $color | |
} | |
return $isAllRed | |
} | |
$fruitsAllRed = @( | |
@{name = 'リンゴ'; color = '赤'}, | |
@{name = 'イチゴ'; color = '赤'}, | |
@{name = 'サクランボ'; color = '赤'} | |
) | |
$fruitsNotAllRed = @( | |
@{name = 'リンゴ'; color = '赤'}, | |
@{name = 'イチゴ'; color = '赤'}, | |
@{name = 'メロン'; color = '緑'} | |
) | |
function Test05_Good_Every_Pipeline($fruits) { | |
$color = '赤' | |
# 条件: すべての果物が赤色であること(簡潔版) | |
$fruits.color | % {$ret = $true} {$ret = $ret -and $_ -eq $color} {$ret} | |
} | |
function Test05_Good_Every_Linq($fruits) { | |
$color = '赤' | |
# 条件: すべての果物が赤色であること(LINQ版) | |
[System.Linq.Enumerable]::All( | |
$fruits.color, | |
[System.Func[object, bool]] { | |
param($x) $x -eq $color | |
} | |
) | |
} | |
Describe 'PowerShellで条件文をきれいに書く方法5選' { | |
Context '1.包含演算子で演算子の数を減らす' { | |
$result = '赤' | |
It 'Test01_Bad' { | |
Test01_Bad 'リンゴ' | Should -Be $result | |
} | |
It 'Test01_Good' { | |
Test01_Good 'リンゴ' | Should -Be $result | |
} | |
} | |
Context '2.Avoid Else, Return Early の掟に従う' { | |
$result = '量が多い' | |
It 'Test02_Bad' { | |
Test02_Bad 'リンゴ' 12 | Should -Be $result | |
} | |
It 'Test02_Good' { | |
Test02_Good 'リンゴ' 12 | Should -Be $result | |
} | |
It 'Test02_OverdoReturnEarly' { | |
Test02_OverdoReturnEarly 'リンゴ' 12 | Should -Be $result | |
} | |
} | |
Context '3.引数の検査処理は関数の機能でなくす' { | |
$result = '1個のリンゴがあります!' | |
It 'Test03_Bad' { | |
Test03_Bad 'リンゴ' 1 | Should -Be $result | |
} | |
It 'Test03_Good' { | |
Test03_Good 'リンゴ' | Should -Be $result | |
} | |
It 'Test03_Good_Advanced' { | |
Test03_Good_Advanced 'リンゴ' | Should -Be $result | |
} | |
} | |
Context '4.switch文よりHashTableが単純でよい' { | |
$result = @('リンゴ', 'イチゴ') | |
It 'Test04_Bad' { | |
Test04_Bad '赤' | Should -Be $result | |
} | |
It 'Test04_Good' { | |
Test04_Good '赤' | Should -Be $result | |
} | |
It 'Test04_SplattingDemo' { | |
Test04_SplattingDemo | Should -Be $true | |
} | |
It 'Test04_SplattingPramName' { | |
Test04_SplattingPramName | Should -Be $true | |
} | |
} | |
Context '5.ANY は -in 、ALLはForEach-Objectを上手く使う' { | |
$fruitsAnyRed = @( | |
@{name = 'リンゴ'; color = '赤'}, | |
@{name = 'バナナ'; color = '黄'}, | |
@{name = 'ブドウ'; color = '紫'} | |
) | |
$fruitsExceptRed = @( | |
@{name = 'バナナ'; color = '黄'}, | |
@{name = 'ブドウ'; color = '紫'}, | |
@{name = 'メロン'; color = '緑'} | |
) | |
It 'Test05_Bad_Any' { | |
Test05_Bad_Any $fruitsAnyRed | Should -Be $true | |
Test05_Bad_Any $fruitsExceptRed | Should -Be $false | |
} | |
It 'Test05_Good_Any' { | |
Test05_Good_Any $fruitsAnyRed | Should -Be $true | |
Test05_Good_Any $fruitsExceptRed | Should -Be $false | |
} | |
$fruitsAllRed = @( | |
@{name = 'リンゴ'; color = '赤'}, | |
@{name = 'イチゴ'; color = '赤'}, | |
@{name = 'サクランボ'; color = '赤'} | |
) | |
$fruitsNotAllRed = @( | |
@{name = 'リンゴ'; color = '赤'}, | |
@{name = 'イチゴ'; color = '赤'}, | |
@{name = 'メロン'; color = '緑'} | |
) | |
It 'Test05_Bad_Every' { | |
Test05_Bad_Every $fruitsAllRed | Should -Be $true | |
Test05_Bad_Every $fruitsNotAllRed | Should -Be $false | |
} | |
It 'Test05_Good_Every_Pipeline' { | |
Test05_Good_Every_Pipeline $fruitsAllRed | Should -Be $true | |
Test05_Good_Every_Pipeline $fruitsNotAllRed | Should -Be $false | |
} | |
It 'Test05_Good_Every_Linq' { | |
Test05_Good_Every_Linq $fruitsAllRed | Should -Be $true | |
Test05_Good_Every_Linq $fruitsNotAllRed | Should -Be $false | |
} | |
} | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment