C#: try-catchの認知負荷

人の書いたC#のコードを読んでいて、こんなコードに出くわした。

try {
     処理;
} catch(例外)
    例外処理;
}

try {
    別の処理;
} catch(別の例外)
    例外処理;
} catch(ほかの例外)
    例外処理;
}

間にtry-catchの処理にtry-catchが続けて書かれていて、書き方的な側面から見ると、これは下記のようなひとつのtry-catch文にまとめることができるハズだ。

try {
    処理;
    別の処理;
} catch(例外) {
    例外処理;
} catch(別の例外) {
    例外処理;
} catch(ほかの例外) {
    例外処理;
}

例外処理はフットプリントが大きいから極力使わないとか、そういう話は置いておいて、果たして書き方としてどちらの方が良いのだろうか?という気持ちになった。

処理⇒例外が近くに記述されている方が、コードを読む上での認知負荷は小さくなるように思うし、ひとつのTRY構文の中に複数の例外パターンが潜んでいる状態の方がコードを読む上での負担は大きいように感じる。

一方で、try-catch文を何度も書かずにまとめたほうがコードの見た目的にスッキリと見えるような気もしていて、スッキリしたように見えるならば、それはそれで認知負荷が小さい事の証左であるようにも思う。

結局、一カ所にまとめる方向でリファクタリングを進めるようにしているのだが、果たしてこの判断が正しいのか?と思ったのでメモに残しておく。

10.9両国大会を見てきました

新日本プロレスのDESTRUCTIONシリーズ千秋楽、10.9両国大会に行ってきました。

年内に関東で行う大きな大会としてはこれが最後という事や、2カ月近いシリーズを走り切った大会という事、タイトルマッチ目白押しだったこともあって多少期待していたのですが、いい試合はあったものの全体的にはちょっと消化不良気味です。

まず、メインがIWGP世界ヘビーなのに、前評判はJ5GのXが誰になるのか?という話題で持ち切り。当日一番の盛り上がりも、第1試合のXこと上村優也の登場だったように思います。

2年ほどアメリカを中心に研鑽を積んできた上村ながら、凱旋初日の試合は人数が多いタッグ戦で、どれほど成長しているのかをじっくり楽しむ機会が与えてもらえなかったのも残念です。

10試合近く組まれた全試合も、個人的に印象に良かったなあと思えた試合はNEVER無差別級王座ぐらいで、他のベルトがかかった試合は全般的に選手が疲れている感じがしましたし、IWGPジュニアヘビー級に至っては、最後の3カウントであからさまにマイクベイリーがリング外で一息ついている様子が見えてしまったので萎えてしまいました。

(STRONG STYLE vs 本隊7番勝負の大団円感は、試合の内容も良かったので満足しています)

あと、全般的にリング外の小さな範囲での闘いが多く、せっかく高い金を払って見に来ているのにとても見づらい試合が続いたり、選手のアピールも正面側ばかりを意識したものが多くて、ライブのお客さんよりも放送の見栄えを重視したような展開ばかりで残念に感じました。

さて、これで1.4東京ドームメインのカードも決まったので、あとはじっくり残りの試合を追いかけながら年内残りのプロレスを楽しみたいと思います。

PowerShellでパスワードの入力を受け付ける

Azure CLIのような汎用的なツールを使っていると、自分の用途に特化させたスクリプトにまとめたくなることが良くあります。

最近だと、私はPowerShellのスクリプトをよく書いていて、先述のAzure CLIの様々なユーティリティをスクリプトとしてまとめて、社内向けツールとして活用しています。

その作業の中で、ログインパスワードのような入力を受け付ける必要があり、少し調べて対応したのでメモとして残しておきます。

具体的には、よくあるこんな使い方を想定しているものです。

パスワード入力のイメージ
今回のスクリプトの用例

要するに、パスワードの入力を「*」でマスクして受け付けて、セキュアに扱おうというものです。

具体的には、こんなスクリプトを書いて利用しています。

function InputPassword($prompt) {
    $pass = (Read-Host $prompt -AsSecureString)
    $bpass = [System.Runtime.InteropServices.Marshal]::SecureStringToBSTR($pass)
    $spass = [System.Runtime.InteropServices.Marshal]::PtrToStringBSTR($bpass)
    return $spass
}

$account = (Read-Host "Input Account Name")
$pass = InputPassword "Input Password"

よく使うユーティリティなので、 InputPasswordという関数に処理をまとめていて、外部から入力プロンプトを指定できるようにしたうえで、この中でパスワード入力に必要な処理をすべてやるようにしています。

関数の中でやっている事は、Read-Hostに-AsSecureStringオプションを付けてセキュア文字列として入力させることと、そこからBSTRへの変換、さらにバイナリデータから後続の処理で使える文字列形式への変換を経ています。

PowerShellは対話型のシェルとしてはイマイチに感じていましたが、(VSCodeの強力なエディタ機能も相まって)スクリプト環境としては中々出来が良く、最近気に入って使っています。

(数年ぶり何度目かで聞いた話題で、まだ生きていたのかという気持ちになりましたが)VBScriptが廃止されるというニュースがありましたので、VBScriptが担っていたような分野でも広く普及してもらいたいものです。

PostmanのPre-request Scriptを使って、form-data形式のリクエスト内容を書き換える

現在時刻をリクエストのデータに含めたい場合に、Pre-requestでデータの書き換えを行いたいケースがあります。

ネット上を探してみると、結構ややこしい方法で書き換えしている例が多く見られたので、私がやっている方法を共有しようと思います。

例えば、StartedAtというパラメータに1分後の時刻を渡してテストする場合には、Bodyタブでform-data形式のリクエストを準備した上で、このようなPre-request Scriptを書きます。

var startedAt = new Date();
startedAt.setMinutes(startedAt.getMinutes() + 1);
const formStartedAt = pm.request.body.formdata.find(item => item.key == 'StartedAt');
formStartedAt.value = startedAt;

肝はbody.formdataから、キー名でfindして取り出してきたオブジェクトは、そのままform-dataの対象データに対する参照になっているため、valueを書き換えてやればリクエストの値が書き換わるという所です。

Postmanは、newmanというツールを組み合わせて使えばパイプライン上でのテスト自動化も行うことができる強力なツールなので、積極的活用すると良いと思います。

C#: ValueObjectでswitch式を使う

※アイキャッチ画像は、話題の生成AIで作成してみました。

public record UserType
{
   public static readonly UserType NormalUser = new(0);
  public static readonly UserType PremiumUser = new(1);

private UserType (byte value ) => Value = value;

public byte Value {get;}

public static UserType Parse(byte value) =>
value switch
{
0 => new UserType(value),
1 => new UserType(value)
_ => // throw Exception
};

例えばこんなValueObjectがあるとしたとき、これは定数として定義されていないので普通通りやるとswitch式の条件に使うことができない。

public string hogehoge()
{
  UserType t = repository.FindUserType();
  return t switch {
  UserType.NormalUser => "無料会員",
  UserType.PremiumUser => "プレミアム会員",
  _ => "会員ではない"
};

「ValueObjectなので、定数っぽく使ってswitchに載せたい」というのが書き手の意図なわけだけれども、C#の文法上これは許されていなくて、この書き方ではコンパイルエラーになってしまう。

そこで、最近のC#に導入されている型のパターンマッチングと組み合わせて、not null when~を使うとそれっぽく書くことができる。

return t switch
{
  not null when t == UserType.NormalUser => "無料会員",
  not null when t == UserType.PremiumUser => "プレミアム会員",
  _ => "会員ではない"
};

項目が増えるとnot nullの羅列になるので、ここのところはシンタックスシュガー的なアシストが欲しいなと思う今日このごろ。(あるいは、もっと良い書き方を知りたい)

アウトプットを続けていこう

日記的に思ったことや感じたこと、あるいは技術的なメモなどをアウトプットしていこうと思って、だいぶ前にVivaldiのブログスペースにスペースだけは用意したものの、その後ずっと放置していた。

いい加減色々とインプットしたものがたまってきたり、職場が変わって2年ぐらい経とうとしていて落ち着いてきたこともあったりするので、こうしてポストしてみようと思い立った。

どのぐらい続くかわからないけれど、飽きない程度に、アウトプットを続けていけるようにしたいと思う。