Skip to content

Instantly share code, notes, and snippets.

@nimzo6689
Created October 6, 2018 05:58
Show Gist options
  • Star 1 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save nimzo6689/9bba84c4a01c5e65825286a57535721c to your computer and use it in GitHub Desktop.
Save nimzo6689/9bba84c4a01c5e65825286a57535721c to your computer and use it in GitHub Desktop.
Qiita用「PowerShellでもっといい条件文の書き方5選」
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