我が名はなんとか菜である!

主に技術系の記事を書きますが、ポエムも混入します。

改善策が分かっている(つもり)なのにやろうとしないという病について

今日はサイゼで書いてる。 ちなみに僕は深夜営業なくした件についてそれなりに肯定派です。(何?)

今日のはガチで日記みたいな感じなので技術要素もレビュー要素もありません。淫夢要素もないです。

続きを読む

Outer Wilds をやって新たなゲームへの価値観が芽生えた気がする話【途中までネタバレなし】

やっとDLCの Echoes of the Eye までクリアできたので感想を書きます。
50時間ぐらい掛かったのかな?全編配信でやったんだけど最後まで見てくれた人は本当にありがとうございました。

途中から結末に関する内容を含むネタバレあり(「続きを読む」以降)になるのでやってない人はこの記事読まなくてもいいからやってくれ、頼む。

store.steampowered.com

今日はモスで書いてる。

ゲームをやってきてかれこれ26年ぐらいになるが、5年ごとぐらいに「それまでのゲームへの価値観を変えるゲーム」に出会ってきた。

僕の中でそのゲームを挙げると、

26年間で5年ごとのはずが余裕で5本以上になってしまったけどまあ細かいことはいいとして、

このラインナップの中に僕は Outer Wilds を加えたいと思う。

このリストに入っているゲームは、前述のとおり僕の価値観を変えたゲームであるわけだけど、具体的にはそれぞれ「3Dゲームの楽しさ」とか「ネットワーク越しでやる対戦ゲームの奥深さ」とか「3D空間の新しい活かし方」のように、新たな価値観の基準を僕に与えてくれた。

Outer Wilds は、僕にとって「探索ゲームの楽しさの基準」を与えてくれたと思っている。

正直言って、いままで探索ゲームの類はあまり好きではなかった。
なぜなら、「そんなのしらみつぶしするしかねーじゃん」と思っていたからである。

よーーーく見ると、確かにヒントらしきものは示されていたりするのだけど、でもそれは「言われたら確かに分かるけど…」のような、あまりすっきりとしないヒントであることが多かった。

特に、この傾向は2010年代にネットで流行っていたフリーのツクール製ホラーゲームによく見られた。
要は「探索とは、単にゲームを前に進めるためのフラグ解除作業」というシステムでしかなかったため、どうしてもどのゲームでも同じようなカラクリにならざるを得ず、どのゲームをやってもそこに新しい体験はほぼないに等しかったからである。(もちろん、ストーリー自体はものすごく楽しめたりするものが多かったけど)

しかし、 Outer Wilds はこういった探索ゲームとは一線を画している点がある。

それは、「探索が必ずしもゲームクリアという目的には必須ではない」という点である。

Outer Wilds には、いわゆる「フラグ」のようなものがほとんどないに等しい。

そのため、答えを知っていれば最初からゴールまで一気に飛び込んで、10分以内にエンディングを見ることだってできる。(実際、RTAではそのような映像が繰り広げられる)

ストーリーの導入では、ある日宇宙飛行士となったプレイヤーは、特に目的も示されないまま突然宇宙へと飛び出していくことになる。

※「続きを読む」の内容からネタバレがあります、未プレイの人は引き返してくれ頼む。

続きを読む

AWS の Cloud Watch でアッチッチになった件

日記です。先週みたいに文章量多いと続かないかなと思ったので今日は少なめ。

今日はらくスパ1010神田で銭湯に浸かったあと休憩室で牛乳を飲みながら書きます。

続きを読む

チームリーダー的な立場でのコードレビューが難しいなという話

お久しぶりです。日記です。

今日から喫茶店に入ってパソコン開いたら記事を書くみたいな決まりでやっていこうと思います。

今日は秋葉原のJR電気街口にあるBECK'S COFFEEで書いています。以下、本文。

続きを読む

macOSが嫌い

Appleのイベントがあったタイミングでこんなことを言うと狙っているのかと思われそうだけど、僕は生粋のAppleアンチで、macOSアンチだ。

ハードウェアとしてのiPadProは好きだし普段から使っているが、Appleの展開するサービスはどうしても肌に合わない。

まあそれはぶっちゃけ好みなのでひとまず置いておこう。

僕が言いたいのは、Appleが嫌いな以上に macOSが生理的に受け付けないということだ。

マルチディスプレイへの対応がゴミ

うちでは、会社貸与のMacBookProをクラムシェルモードで、2画面に外部出力して使っている。

自分はプログラムを書くときは最低でも2台のディスプレイが必要だと考えているため、そのような構成になっている。

どちらもWQHDだ。

接続方法だが、1台はUSB Type-Cで直接繋ぎ、もう1台はType-CからHDMIに変換も出来るドックHubを使っている。

で、実はこのType-Cで繋いでいるほうのディスプレイは 本来であればデイジーチェーンに対応している。

デイジーチェーンとはなんぞという人のために説明すると、簡単にいえば「ディスプレイを数珠繋ぎのように接続出来る仕様」のことである。

これを使えば、デイジーチェーン対応モニタに付いているOUT端子から別のモニタを繋ぐと、そのあとはType-Cを一本繋げばそれだけでマルチモニタ環境が出来上がるという非常に便利な物である。

しかしあろうことか macOS はなんと デイジーチェーンに非対応 なのである。

ちなみに今使っているMBPはIntel版なので、M1がどうとか一切関係ない。

Apple自体が「デイジーチェーンなんて対応してもうちの製品ラインナップにそんなもんないしw」という姿勢で、端から対応する気がないようなのである。

この事実を知った時は思わずクソデカため息を付いてしまった。Appleとは本当にどこまで行っても傲慢なメーカーである。

そんなわけで仕方なく、 デイジーチェーンに対応しているモニターを持っているのにもかかわらず、デイジーチェーンを使わずに2本のケーブルをMBPから伸ばして使っている。

閉じた状態のMBPから伸びる2本のケーブルのなんと美しいことやら(棒)

さらに問題は、MacBookProをこれらディスプレイへ接続したときの挙動である。

普段は作業終了時にスリープにして作業開始時にスリープを解除するという運用方法を取っているが、スリープを解除した際に まず一発で映ることはない。

75%ぐらいの確率で、ケーブルを一度外して再接続しないと映りすらしない。

何がムカつくって、25%の確率で映るところである。

一切映らないのであれば、一度接続を解除して繋ぎ直すのを取り敢えず一連のワークフローとして組み込むことで、ある意味妥協することも可能であろう。

しかし、こいつの最大の問題点は 再接続を繰り返していると一瞬だけファンが全開になってOSがハングアップすることがあること である。

映らないからといって再接続を繰り返していると「ヒュン!」などとため息を吐いてmacOSが死ぬのである。 ため息をつきたいのはこっちじゃボケ

これは、MBPに搭載されているディスプレイドライバーがゴミであることの査証である。

本当にAppleにやる気がないのか、それともRadeonのドライバが悪いのか、いずれにせよWindowsではそんなことは滅多に起こらないので、これらに関わっている人間がMBPの外部モニタ対応にやる気がないことは明白である。

マウス対応がゴミ

まあわざわざこんなアンチ記事をここまで読んでいる人は知っていると思うが、悪名高い「加速度設定」のことだ。

macOSでは、Windowsでいう「マウスの精度を上げる」設定がデフォルトでONになっている。

これはどういう設定かというと、「マウスの動き始めはゆっくり動き、しばらく動かしていると徐々にカーソルの速度が上がる」というやつである。

慣れればいいのではという話もあるが、ハッキリ言って このチューニング具合が気持ち悪くて慣れられたもんじゃない

しかも、その設定をOFFにするには zshを開いて以下のコマンドを入力して再起動 する必要がある。

$ defaults write .GlobalPreferences com.apple.mouse.scaling -1

しかも 一度でもまたマウス感度の設定をいじると加速度設定が復活する という嫌がらせのような仕様になっている。

これを考えたやつはリンゴの葉巻でも吸いすぎたんだろうか?

ユーザーの自由な設定を妨げ自ら推奨する設定を押し付ける。僕に言わせれば Microsoftと同じがそれ以上のevil である。

また、マウスホイール回転時のスクロール方向の設定が何故か トラックパッドの2本指スワイプと同期している せいで、マウスホイールを普段使い慣れている方向に設定すると、今度はトラックパッドジェスチャーで操作したときに逆になってしまう。

いや普通そこはどう考えても設定として分離するだろ。

Appleの遥か下に位置する日本のパソコンメーカーでさえその設定は個別に可能だったと思うんだが。

やはり遥か高みにいると下々の声は届かなくなるのだろうか。

マウスカーソルがゴミ

macOSは裏で重たいアプリが動いていると マウスカーソルの操作が非常に重たくなる

コンパイル中にマウスを動かすと、カーソルにガムでも張り付いてんのかってぐらい動き始めでめっちゃ引っかかる。

おまけに動かねえ〜〜〜!!!って言いながらマウスを素早く動かすと 僕はここです!と言わんばかりにデカくなりやがる。 てめえがそこにいるのは知ってるわボケ、さっさと動きやがれ

まあ、この設定は macOSにしては珍しく 切ることが出来るので、速攻で切ってやったが。

Windowsの場合、マウスカーソルの移動には高い優先度をつけて処理を行なっているという話もあるので、まあそこはWindowsの「利点」と言って然るべきなのだろう。 つまりmacOSが劣っているのは仕方がないのだ

何かに付けていちいちクソトロい視覚効果が挟まる

例えばウインドウを最小化・最大化したとき。

なにあの ぬるぅ〜〜〜〜ん っていう動き、誰に求められてあんな動きをすんの?

これについてはmacOSを操作するとき全般に渡って味合わされるので、 macOSを触っている間中ずっと不快である

幸い、この設定を切れるようにするアプリを見つけたので、そいつで視覚効果周りの設定を全て切ってやったところ、だいぶ動作が軽快になり快適になった。

そう、 軽快になった のである。

この設定を切ったところ、明らかにアプリ全体のレスポンスが良くなった。

つまり、 マシンスペックに見合わないなんの役にも立たない視覚効果にマシンリソースが割かれ動作が遅くなっていた のである。

Celeronでメモリ1GBなマシンにVistaを乗っけていた Appleの遥か下にいる日本のPCメーカーと同じことをしている ということだ。

このAppleとかいうメーカーはもうOS作るのやめて筐体だけ作ってて欲しい。

まとめ

今後お仕事を始めるにあたって、パソコンを選ぶ余地があるのであれば 全力でmacOSは避けたい と思います。

【Redux】ActionType, ActionCreator, Actions を書くときの個人的ベストプラクティス

TypeScriptでの話です。 不要論者はさっさと帰れ
バージョンは 2021/02/20 現在最新の 4.1.5 の話ではあるけど、 ReturnType とか as const が使える 3.4 以降が推奨。
ちなみにこの書き方は Redux には一切依存していないので、 useReducer を使うときに書く Action 周りでも使えるため、 useReducer 使ってたけどやっぱり Redux 使いたくなったときも移行が楽です。

ActionType

export const COUNT_UP = "COUNT_UP" as const;

ポイント

  • as const とすることで ActionType の型が string に推論されてしまうのを防ぐ
    • と思ってたんですが、 TypeScript 4.1.5 現在だと as const しなくてもリテラル型に推論されるっぽいのでなくてもいいかも
  • きちんと定数として定義する
    • Reducer の switch-case で使うときに文字列ではなくこの定数名がエディタによって補完されるようになるので変更に強い。(VSCodeならF2の変数名リファクタリング機能で該当箇所を自動で変えてくれる)

ActionCreator

export const CountUp = (increases: number) => ({
  type: COUNT_UP,
  payload: {
    increases
  }
});

ポイント

  • ActionType の定義の真下に書く
    • 無駄に場所を離すと修正するときにダルいので近いところに定義する
  • function は書くのがダルいのでアロー関数で書く
  • 関数名は Upper Camel のほうが見やすいのですき
    • dispatch(countUp(1)) より dispatch(CountUp(1)) のほうがメリハリ付いて読みやすくない?程度なのでプロジェクトと好みに合わせて
  • payload には変数名をキーにしてくれる構文(名前知らない)を使って簡潔に書く

Actions

export type Actions = ReturnType<
  | typeof CountUp
  | typeof OtherAction
>;

ポイント

  • ReturnType は1回、 typeof は毎回
  • なんか ActionCreator をオブジェクトで定義して Mapped Type で一気に生成する書き方も見つけたけど、Utiliy Typeを自分で書かずに組み込み型だけで行けるこれが一番シンプルだと思う
    • 結局 reducer の switch-case で推論ができれば何でも良い

おまけ: Reducer の書き方

export function reducer(state: State, action: Actions): State {
  switch(action.type) {
    case COUNT_UP: {
      return {
        ...state,
        count: state.count + action.payload.increases
      };
    }
  }
  return state;
}

ポイント

  • 戻り値の型をきちんと書く
    • うっかり色々書き忘れて return する state の型が不完全になるのを防ぐため
  • case節内は {} で囲う
    • 好みのレベルだけど、ここで変数を定義したくなったときに eslint の no-shadow に引っかかることがあるのでやっといて損はない。 {} まみれになって嫌なら書かないし、気にならないなら書く、ぐらいでよいと思う
  • default節は書かない
    • default節を書いてしまうと、caseで拾い損ねている Action があってもエラーにならなくなるため

まとめ

そろそろみんなで書き方統一しない??って思ったので書きました。
なにか意見あればブコメでもTwitterでもここのコメント欄でも積極的に書いていってください。