LGのディスプレイ 43UD79-B の入力切り替えをソフトウェア制御で出来るようになるまでの試行錯誤

TL;DR

  • display-switch という OSS を使うと USB 切替器と連動してモニタの入力切り替えができる
  • display-switch は DDC/CI プロトコルでモニタを制御するが、43UD79-B は使えない
  • 代わりにシリアルケーブル接続で専用コマンドを用いれば制御が可能なので、display-switch の on_usb_connect_execute で専用のコマンドを実行するようにすれば解決
  • コマンドはgo で書いて、win,mac で利用するようにした

自分はメインモニタに 43UD79-B を使っていて、会社用の Mac と私物の Windows を接続しています

んで、これの入力切り替えを毎日やっていたわけなんですが、リモコンで操作しなきゃいけないので面倒だし机の上にリモコン置きっぱになるしでまあ不便だったんですよね
もう何年もずっと面倒だと思ったままほったらかしてたんですが、最近 @watiko に以下の OSS を教えてもらったことからことは始まりました

https://github.com/haimgel/display-switch/

このアプリは、USB デバイスの接続を検知してモニタの入力切り替えができる、というもので、USB 切替器を使えば 1 ボタンでマウスやらキーボードやらの切り替えとともにディスプレイの入力切り替えもできちゃう、というわけです

ところがどうもうちのモニタでは上手く動作しない

セットアップしてみるも、どうにも動かない
display-switch はログが親切だったので、そもそもモニタ側が変っぽいのは割とすぐわかりました(モニタの識別子の hex 値が規定の HDMI や DisplayPort のものと違い、 0x0 という値が返ってきていた)

んで調べてみると、Linux 向けの ddc/ci ツールである ddcutil の issue LG 29UM69G fails switching input にたどり着きました

まあなんか LG のモニタでトラブってる人がわんさかいるわけです

その議論を見るに、ddc を raw に操作できる方法があればデバッグできそうとなり、それを探すことにしました

https://www.ddcutil.com/mac_programs/

↑ に Mac 向けのツールなどが紹介されてたりもしたんですが、最終的には m1ddc を利用して、なんとかデバッグできるようになりました

そしてデバッグした結果、結局 43UD79-B は動かないな、という結論になって悲しみを背負ったのであった・・・

他に色々調べたんですが、ddcutil の以下のページにある 43UN700-B という同系列っぽいモニタも結果が NG だったので、DDC/CI での制御はダメそうかなあという結論に。

https://github.com/rockowitz/ddcutil/wiki/Switching-input-source-on-LG-monitors

光明

https://github.com/rockowitz/ddcutil/issues/100#issuecomment-1435477786

このコメントで、マニュアル見てどうこうしている、というのを見かけて、 43UD79-B でもなんか情報あるんじゃないかと見てみたら

EXTERNAL CONTROL DEVICE SETUP

とかいうセクションがあるじゃないですか
いけるやん!

・・・ただしシリアルケーブルを使いましょうという
しかもディスプレイ側の端子は 3.5mm のイヤホンジャックで、定番の D-sub9 ピンじゃない

https://amzn.to/4nRu3Z1

Amazon でこんなのを買って、D-sub9 ピン →USB の変換を買って、両方ストレートケーブルだったのでリバース変換するケーブルを買って・・・など無駄な買い物もし・・・

あと自前のスクリプトが正しいのかも分からなかったので、シリアルケーブル経由で LG43UD79-B を操作するツールを書いてる人がいたっぽいので、これを持ってきて Windows で C#の環境作って VisualStudio でビルドして・・・とかやったりもしました

https://github.com/knarfalingus/LG43UD79

結果、なんとか疎通に成功しました

専用コマンドの実装

とりあえず knarfalingus/LG43UD79 が動いたので、まず powershell で適当に動かすようにしてみました

こんなん。

$c = New-Object System.IO.Ports.SerialPort("COM3")
$c.Open()
$c.Write("xb 01 C0`r")
$c.Close()

CR の送り方がわかってなくて \r とか書いて動いてなかったけど AI 様に聞いたら `r って書くんやでって言われました
AI 最高!

んでまあ動いたは動いたんですが、スリープ時のケアとかそういうの考え始めたらさすがにもうちょい恒久な言語で書きたいってなって Go で書きました

https://github.com/sisisin/op-lg43ud79

https://github.com/bugst/go-serial を使えば、シリアルポートデバイスの通信がクロスプラットフォームに出来るので、これを使って実装しています
自宅用のバイナリを吐くような作りになってはいますが、43UD79-B との通信部分はライブラリとしても使えるような気がします(試してないが)

色々試行錯誤したんですが、最終的には ↓ のような処理にまとまりました

  • シリアルデバイスの一覧から VID,PID を元にして対象デバイスを探し、接続
    • USB 切換器を使っていて、切替直後にデバイスが認識しない場合があるので、3 回ほど sleep & retry を入れる
  • 接続後に、まず Power On コマンドを送信
    • モニタがスリープしてるケースのケア
  • 最後に入力切替コマンドを送信

このコマンドを display-switch の on_usb_connect_execute で実行するようにすれば、USB 切替器の切り替えと連動してモニタの入力切り替えができるようになります :tada:

色々試行錯誤の思い出

  • コマンドを送信しただけじゃコマンドが実施されず、応答を読みこんで初めて反応した
    • そういうものなの?
  • go-serial の port がio.Reader interface 実装されてるので、 io.ReadAll したれ!ってやると止まる
    • io.ReadAll は EOF まで読もうとするが、モニタの返す末尾が EOF ではなく CR なので使えない(なるほどね)
  • CR で終端処理をしなきゃいけないと気付いてなくて、Read がブロッキングされて CTRL+C でも止められなくて悲哀、みたいなことを何度もやった
    • 素人みを感じる
    • signal.NotifyContext と ctx.Done は便利
  • 最初に mac で試していた bash 版スクリプト
DEVICE="/dev/cu.usbserial-FTEM5CHZ"
stty -f "$DEVICE" 9600 cs8 -cstopb -parenb -ixon -ixoff -crtscts raw -echo

COMMAND="$1"
SET_ID="$2"
DATA="$3"

# コマンド形式: [Command1][Command2][ ][Set ID][ ][Data][Cr]
echo -ne "${COMMAND} ${SET_ID} ${DATA}\r" > "$DEVICE"
timeout 0.1s cat < "$DEVICE" 2>/dev/null
  • そもそもデバイス探してそこに向かって通信投げるみたいなの初めて書いたので新鮮だった
  • go-serial がクロスプラットフォームに動くおかげでマジでほとんど何も考えなくても win,mac で動くように作れて最高。やはりこういうときに Go 言語はかなりいい
  • Rust に入門した
    • モニタの挙動確認がしたくて、display_switch のログ出しを変更する PR を出した
    • if が式な言語久しぶりすぎる

謝辞

display_switch 教えてくれたり、調査に色々付き合ってくれた @watiko に感謝 :pray:

おわりに

ということで無事ちゃんと動くようになりました。最高!

小さいPull Requestを作る工夫

社でPull Request(以下PR)を小さくする工夫の話が盛り上がっていて機運だったので書いてみる

自分は普段PRを作るときも見るときもPRサイズを小さくするようにしている
見るときというのは、レビューにアサインされたときの話で、PRのサイズが大きかったら分け方の方針の提案込みで分割するよう依頼している

そんな自分が考える、PRがでかくなってしまうケースとそれに対して小さくするアプローチ、というのを書き出してみようと思った次第。

なぜPRはデカくなるのか

小さいPRを作る工夫、とは言ってみたが、むしろなぜPRはでかくなるか、そこからの対策、というブレークダウンで考えてみることにする

  • PRを小さくしようとしていない
  • 一つのことを実現するのにデカくなってしまう性質の機能である
  • サーバーとクライアント一緒くたに作った
  • 一度の変更で複数のことをやっている
  • テストを丁寧に書いた
  • 依存関係的に1箇所変更すると修正箇所が波及してしまう
  • 自動生成コードを含んでいる

これらに対してどういうアプローチで対処するかを考えていく。

そもそも小さくしようとしていない

意識的に小さくすることを避けている

それならそれで良いと思う

小さくすることを考えたことがない

まずは小さくすることを考えてみてもらうということでひとつ

小さくすることに心理的抵抗がある

小さくしてみようと頭では思っても実際にやるのは面倒・大変といった気持ちを持っているケース

自分が過去に辿ったのは↓みたいな思考だった。(他の人と話す中で同じような考えを持ってそうと思ったこともあったような気がする

  • やってみたらでかくなった
    • 作りきったしそこから分けるのは手間が多い
  • そもそも小さくするのは難しい
    • 設計をちゃんと考えるのはコストが高い(やってみないと分からないことが多いケースでよくある)
    • かといって考えきらずに決め打ちで始めると手戻りがち
    • それなら最初から一気通貫でやって動くものを作るのが手っ取り早い

このようなケースでは以下のような考え方・アプローチで対策している

→大きくなってしまっても構わないので、まず荒削りで作りきってしまい、そこから分割を考える

これは設計とかも固まってないなら泥臭く雑でもいいから正常系1個だけ最低限通すとか、とにかく製品の品質には足りないけどごく最低限動くレベルで作り、
それを元にして分割を考えるというやり方

不確実性が高い状況だとこういうアプローチのほうが結果的には速いことも多い(はず)
PRのサイズとは異なる文脈だけど、設計を明らかにするとか、考慮事項の洗い出し、規模感の把握といった点でも有効な方法なので、割とよくやる

このアプローチを取ると、既存のロジックにどう手を加えればいいかが明らかになり、事前に必要なリファクタリングや作るべきモジュールがはっきりするので、
その単位でコードを清書してPRを出していくとある程度整理された状態でPRを出していける

このアプローチは大掛かりな機能だと難しいけど、そういうケースはそもそももっと上流工程のテクニックが必要になると思う

一つのことを実現するのにデカくなってしまう性質の機能である

既存のモジュールがデカい・結合度を下げることもアーキテクチャ上困難・その上で影響範囲が広いケース
例としてTypeScriptの型システムに機能を追加する、みたいなの

多分わりとどうしようもないと思う
でも普通のwebアプリケーション開発の範囲でこういう機能・モジュールになることってそんな内容な気はするのであんまり考えたことがない
テスト充実させておくとかしかないんじゃないかなあ・・・

サーバーとクライアント一緒くたに作った

機能を一気通貫で作ったケース。(サーバーとクライアント、みたいなのはあくまでも一例)
よくある。わけよう。

こういうのはcommitごちゃまぜになってたとしても技術的な境界で分割すればそんなに大変じゃないはず
ここでいう技術的な境界は、例えばクライアントサイドとサーバーサイド、サーバー内なら、DBアクセス層・ドメイン層・プレゼンテーション層などのアーキテクチャのレイヤー、のようなビジネスドメインではなく利用している技術による境界を称したもの

サーバーとクライアントサイドを実装した、という場合なんかは素朴に依存関係の末端から順に分割するようなやり方で十分通用すると思う

  • まずDBアクセスの実装だけ作る
  • 次にAPIのエンドポイントを作る
  • クライアントからAPIを呼び出す部分を作る
  • ...

みたいなの
アジャイルプラクティスの文脈で、よくこういう作り方をすると全部結合するまで動かない、というデメリットを挙げられるやり方だけど、
そもそも全部作っちゃってから分割するときにこの方法を取るならそのデメリットもあまりないのでまあ良いかなと

サーバーで非互換な変更を加えてクライアントも同じPRでそれに対応、みたいなケースもありえるかもしれないけどそれが許されるなら手間をかけてまで分割しないほうがいいのかもしれない

一度の変更で複数のことをやっている

この機能作るならライブラリアプデして〜リファクタして〜あとついでにバグってるやつ直して〜とかしちゃうやつ
よくある。わけよう。

こういうケースは大体適当なところでcommit作らずに書き進めてごちゃらせがちなんで、1commitの粒度をある程度小さくすることを習慣にするのがよい
(と言いつつ自分は静的型付け言語で書いてると変更に対して強気にいられるからってクソデカcommitになっちゃいがちなんだけど・・・

ともあれ、commitさえ変更がそれぞれ独立した形で分かれていればPRを分割するのは簡単なので、そのような習慣を作っていくと良いと思う

この話題の発端の同僚氏が書いてたのがちょうどそんな内容の記事 だったので張っておく

conventional commitにするというのは自分もやっていて、大体1commitでやることはconventional commitに分類できる粒度になるようにしている

(以下余談)
記事にはcommitはあんまりしないとあったけど、自分はマメにする派
自分は割と、「こうやればうまくいくんじゃなかろうか?」→(やってみる)→ダメだったので消す、というのを頻繁にやるので、commitはセーブポイントみたいに使いたい感じ
大体commitするときは「なんらかのキリのいい状態」(コンパイルが通るとかテストが通るとか)にしておきつつ、適当に変更してダメなら消すをカジュアルにやっている

テストを丁寧に書いた

テスト、プロダクションコードの変更に対して何倍ものコード量になるんで、ある程度仕方ない
これもまあしょうがないと思う

一個上の 一度に複数の変更をしない というのを心がけることでテストでのPRサイズ膨らむのを抑えられるので、そういう感じで頑張る

依存関係的に1箇所変更すると修正箇所が波及する

静的型付け言語・モノリシック・大きいコードベースなどでリファクタリングとかするとありがち
(静的型付けはそういうの言語機能で一発で出来ちゃうからどっちかというと やりがち 、のほうがニュアンスが近いかも)

そしてそういう状態そのものをどうにかする変更もデカくなるんでまあまあ踏ん張りがいる

こういうケースでは、変更内容がリネームやクラス・DBのテーブルへのフィールドの追加などのような単純な変更のみにするよう心がける
変更も前述した「一度の変更で複数のことをやっている」とのあわせ技で大きくなるケースもありがちなんで、単純な変更になるようにしつつ単独でPRを上げるのが効果的だと思う
(というか他にやりようあるのかな・・・

現実問題、単純な変更だけではいかないこともあると思う
その場合は可能な限り複雑さが局所的になるように設計して変更を加える、といった設計面でのアプローチで解決することになると思う
必要ならその準備のリファクタから入ったりしていくこともあるだろうが、まあ前提が影響範囲がデカいものなのでとにかくキツい・・・
そんな場合は歯を食いしばり両の腕のマッチョでシバいていくしかなさそう、辛い

自動生成コードを含んでいる

まあ割としょうがないんで、自動生成による変更だけのPRに分けましょう

commit分けておけばこの手の分割は簡単なのでやはりcommitは粒度を適当にしておこうということで


というわけでここまででPRがデカくなる理由からのPRを小さくするアプローチを書いてみた
紹介したアプローチを選ぶ指針とか、そもそも最初から小さくしようと思った場合のアプローチとかも書きたかったけどまとまりがなくなると思ったのでやめていおいた
機会があれば書くかもしれない(こういうの一生書かなそう)

chattunのSocket Mode対応をした

まだマージしてない けど、普通に普段から動かして使えてるので苦労話というか愚痴を書く


とにかくSlackAPIがしんどかった
一番しんどかったのは「EventAPIでユーザー固有のイベントを受け取れるようにする」という部分
これ今回の実装の前にEventAPIの調査段階(つまりchattunの初期実装の頃、2018年10月頃。当時の記事)から何度も調べて何度もわからずに来て今回ようやく見つけられて勝利に至った
userScope設定すればいいなんてドキュメントいくら探しても書いてなくてなんなの・・・ってなってしまった・・・

そもそもなんでSocket Mode対応をしたのかって、現職のslackワークスペースでも使おうとしてアプリ作ったりしたらどう頑張ってもRTM APIを使ったアプリのOAuthフローが通せなくてこれもう動かないのでは・・・と途方に暮れて仕方なくやったという出発点からしてSlack APIにしんどさを感じてしまう RTM APIはもはやいつdeprecatedになっても不思議じゃない気配があるけど、ドキュメント的には有効なAPIとして記載されてるので使えないはずはないし、前職では動いてたんだから動かせないはずがないのだけど・・・

まあRTM APIは間違いなくいずれ廃止するであろう機能なので余力があるときにやれて良かったとは思いつつ・・・

完全に愚痴になってしまった

転職して1ヶ月が経った記事

6/1 付でstand.fmへ入社してそこから1ヶ月経ったので感想とか書きます (あとLAPRASでキャンペーンやってて転職したことを紹介するとアマギフもらえるのもあり)

主にやってること

プロダクトはクライアントサイドReactNative・サーバーサイドNode.jsでflowを使っていてフルflow+js、DBにmongodb+atlas、インフラがGCPでサーバーはk8sという感じの構成

自分は経歴的にはフロントエンドエンジニアっぽいけどstand.fmではバックエンド中心にやっている
最初の1ヶ月ではライブ配信画面でリアルタイム処理をしているWebSocketサーバーの改修とか開発環境の改善をあれこれやったりしていた

雑多な思ったこと

全部js+flowなのがすげえいい

  • 長いことjsやってきたので自分の主戦場でやれてる感じでいい
  • かなりスムーズに開発に入れてよかった
  • 言語が統一されててモノレポなので横展開しやすいというのも単純にいい
  • やっぱ静的型付けは良い

不安はあったけどちゃんとやれてそうでよかった話

  • なんだか面接での評判が良かったので期待に応えられるかとか、前職で5年もいたので新しい環境にスッと入れるかとか、そういうのが不安でした
  • でも楽しくやれてるので良かった
  • twitterで書いたけど早くも同僚からフィードバックをもらう機会があって、その内容も戦力になれてそうという実感を得られるもので良かった

リポジトリの流速がめちゃくちゃ速くて目が回ってる

  • 会社の規模は小さいけど1つの開発チームとしてはQAやPM含め25,6人な体制で自分的には過去最大規模。速い。
  • すごい
  • 前職最後にやってたプロジェクトがずっと4〜5人のチームで大体のプルリク見る余裕があったけど現職ではslackに流れてくるgithubのコメント通知を見ることすらままならない
  • すごい
  • なるべく目を通そうとか自分が関連してるモジュールのコードが変更されてそうだったらキャッチアップしとこうとか思ってたけど全然無理そう(というか無理)
  • すごい
  • なんとか流し見だけでもして自分が力になれそうだったり関係が深そうなところは見に行ったりするぐらいで精一杯なかんじ
  • すごい
  • 結構みんな午前中に活動していておそおきの自分は勤務開始してまず圧倒的未読が読みきれないところから一日が始まる
  • (みんな早起きできて)すごい

前職との比較で得るものがあった

  • 前職でログ集約とかしたいと思ったけど結局やらなかった、ということがあったところから現職でログ集約だったりをしている状況に身を置いてみて、その良さの実感と、「そのソリューションはプロダクトにとって必要なのか?」という問いが弱いままやろうとするのは違うよなということの再確認ができたりした
    • 前職では結局必要性が低かったんだということを実感
    • 現職では問題の特定とかにこれなしではあまりにも時間かかりすぎることが身を持って感じた
  • webはデプロイ楽で良い
    • それなりに自明だけど、実感が伴うようになった
    • ネイティブで問題が起きたときにログを仕込むところからスタートだと正攻法ではとにかく解決までが長くなる
      • これどうやってリードタイム縮めるの・・・
  • 立場が変わったので見えるものがあった
    • プロダクトをリードする立場じゃなくなった→(これこの記事書いてて思ったけどこの目線で日々を過ごしてなかった気がしてきた)
    • 新規参入者として活動し始めた→受け入れる立場の逆をやったことになる。なんとなく自分が受け入れるときに苦労、というか時間を掛けてやっていたことを自分ではあまり世話してもらわずに済んだような気がしてて、ここに自分は何が違ったのか?を自問する余地を得た(あんまり考えられてないまま日が過ぎてしまってるけど)。
      • 意識してたのは、なるべく背景を引き出そうとする・issueだったりコードの意味だったりは追える範囲ではなるべく追うようにした・あてがわれたissueに関連するコード・モジュールについては極力広く追いかけるようにしたりした・あんまり聞こうとすると無限に聞きたくなってしまうのである程度「多分こうじゃろ」という気分で動くようにした・個別具体のやり方はなるべく自力で調べるようにして学習に費やした、らへん
  • 悪い癖はやっぱり現職でも出ちゃうなあと感じている
    • 重い解決策ばっかり出しがちで議論の行き止まりに誘導しがち
    • 細かい気になることをほっておけないがち
      • 結果的に1ヶ月間で開発環境改善プルリクたくさん出すことになったがメインでアサインされたissueの進捗には影響出てるのでアレ
      • CI職人もした
  • 前職に比べて色々と進行が速いと感じるんだけど何が違うんだろう?は全然見えてこない
    • 多分マンパワーよりは仕組みだと思うんだけど
    • モノレポでやってるがちゃんと開発スピード維持できててすごいと感じる

その他

せっかく音声配信のアプリ作ってるので自社製品でこんなこともやってみた

よかったら聞いてみてもらえればと

転職活動に関して

※この記事は LAPRAS株式会社の「あなたの入社エントリにスポンサーさせてください」キャンペーンに参加しています (https://note.lapras.com/campaigns/sponsor/)

というわけで↑のライブ配信でも触れてるけど、LAPRASのキャンペーンのことがあるので書きます

  • LAPRASでstand.fmの募集を見て、会社紹介スライド見て興味が出た
  • LAPRASから申し込み
  • そのままトントン拍子
    • 全部オンラインだったので都合10日ぐらいで決まった

LAPRAS使ったけど最初に申し込みしてからはstand.fm側に提示されたと思われるツールで日程調整とかをしていて特に手間を感じなかったのでその点は良かったのかな
職探しという点ではあまり活用できてないけど、頂く求人の連絡は良さそうなものが多い印象なのと、クローリングして自分のアウトプットを集約してくれたりスキル可視化とかを勝手にやってくれるのが便利なので次回があれば(いろいろな意味で)、また使いたいという気持ち


というわけで転職して1ヶ月経った振り返りでした
頑張っていきたい

最近やったMacの環境改善

色々やったので備忘録

snap の導入

  • option+[number]で設定。次の項目のkeylayout変更も必要。割り当てたアプリは↓。とりあえず頻繁に使うやつだけ端っこに設定したので5~7は適当に穴埋めでsystem preferenceとかが入ってる
    • 1: chrome
    • 2: iterm
    • 3: vscode
    • 4: rubymine
    • 8: discord
    • 9: slack

option + keyでspecial character入力されないようにkeyboard layout変更

  • この記事 でリンクされている.keylayoutファイルをダウンロード
  • ファイル名とファイルの中の keyboard Elementのname属性を US_without_sp_chars に変更(元の名称がアレすぎる)
  • system preference > keyboardの入力ソースでこれを追加

karabiner-elementsで左右optionにかな・英数をアサイン

今までgoogle imeのショートカットを使ってたけど地味にエディタとかとぶつかるのと、↑のkeyboard layout変更で英数入力でgoogle imeを使わなくなったので。

  • ここ から For Japanese (日本語環境向けの設定) (rev 6) の設定を探してきてimport
  • optionキーでかな英数割当のやつを有効化
    • ほんとはcmdキーのほうが良い気がするんだけど、前にcmdキー使って誤爆多すぎて使うのやめた記憶があるので一旦optionキーを使うことにした

karabiner-elementsでhhkbモードを設定

なんか見つけたのでもののついでに。 リアフォの十字キーは遠いのが結構ストレスだったのでこれで多少便利になると思うけど慣れるまで時間かかりそう

  • Happy Hacking Keyboard Compatible Mode (rev 2) をImportして HHKB Arrow Mode を有効化
  • 左caps、右ctrlをfnにアサイン

Macの入力ソースからUSとかの消せないやつを消す方法

たまーに keyboard 周りいじるとその度にわからんってなってるので書き残しておく

  • 日本語を追加
  • 日本語入力ソースで英数にチェックを入れる(英数入力できることを OS へ伝える)
  • US が消せる
  • 何故か日本語も消せる ← これ謎ですよね

参考:

https://www.karakaram.com/deleting-alphanumeric-input-sources-on-macos-bigsur/


2025/11/18 更新。日本語追加するだけじゃ消せなかった。

Rubyの静的型解析を触った感想を書いたりする

この記事は Opt Technologies Advent Calendar 2020 10 日目記事です
12/25にリリースしたRuby 3.0を使った話をしているので時空が歪んでるように見えますが気のせいです

9 日目の記事は @shachitaku さんの M5StickC x JoyStick HATで寝ながらパソコンを操作できるBluetoothマウスを作ってみた です
11 日目の記事は @shoyaokayama さんの LINEThingsとM5CoreInkを使ってO2Oマーケティングを体験してみる です


Ruby 3.0の目玉機能として静的型解析のサポートが挙げられるでしょう
最近仕事ではRailsを書いてるけど、もともと静的型付け派な自分としては大変気になる機能なので試してみて感想を書き残しておこうと思った次第

良かった点は静的に型情報を解析できるようになる、に尽きるので、基本的に足りない点を指摘することに終始する点、ご了承いただければと

結論

まだ早い(そりゃそう)
自分が求める体験との乖離が結構大きかったのと、エコシステムが粗く、これからどんどん変化していくと思うので追従が当面の間かなり大変だろうという所感
(実際に使ってフィードバックしたりして貢献していかないと進化していかないだろうから使いたい気持ちもある)

触った感想とか

  • steep checkが遅い
    • rails newしただけのコードを全解析すると15secほどかかった(MacBookPro 13inch 2019モデル)
    • ファイルに閉じてるエディタ上での解析は気にならないけど、やっぱりクラスを書き換えたらそのクラスの利用側でコンパイルエラーが出てる場所を全て見る、というような利用シーンにプロジェクト全体のコンパイルは必須なのでこれが遅いのはしんどい
  • 実装を変更するたびに型定義を更新しないといけない
    • watchモードもなさそう・仮にあったとしてもtsでの経験上、ファイルシステムを挟んでしまうと遅くなるので今後パフォーマンス対策大変そう(Steep,TypeProf,エディタがそれぞれ全て速くないと良い開発体験にならなそう)
    • これは仕組み上しょうがないので、上手いこと良い開発体験になるエコシステムが出来てくるといいなあと思った
  • エディタサポートが弱い
    • RubyMineやSolargraphが「実装への」定義ジャンプまでやってくれるのに対してsteep-vscodeは*.rbファイル上で実装を書くときにメソッドのシグネチャが補完されるだけ
    • RBSをRuby本体にバンドルしているので、LanguageServer実装も本体に入れて実装へのジャンプや型定義取得などが自在にできるようになっててほしい(それが出来るのかは・・・)(RubyMineの定義ジャンプなんかはRails向けに相当気を利かせた実装になってるようだし、それ相当の体験をRuby本体がバンドルするようなツールが出来るのかというと・・・みたいな)
  • 現状はRBS作ってもuntypedな部分を厳格にしようとすると生成したコードを書き換える必要がありそう?
    • 理想的には実装を書き換える→TypeProfによるコード生成→自動で補完!だと思うけど、そうなると自動生成されたRBSファイルを直接変更じゃなくて上書きのような形にしないと継続的にTypeProfの世話になることが出来なくて難しそう。どういう方針なんだろう
  • 型定義ファイルの取得方法がgemなどのツールでサポートされていない(git submoduleとかで取ってきてそのパスを指定する必要がある)
    • これはSteepの問題ではあるけど、SteepってRubyにバンドルされてるわけじゃないから、そこまでgemなどの公式サイドのツール側でサポートしてくれるようになるんだろうか?という疑問はある
  • irbのようなREPL環境でも型情報が使えるようになってほしい

その他の感想

そもそも疑問なんだけど、型定義ファイルの生成と型定義ファイルそのものを扱うライブラリが本体にバンドルされても静的解析ツール(Steep)が本体に入らないのってどういう理由なんだろうか
RBSファイルの存在は最終的にSteepありきになるはずなのでSteepに特化した機能を入れたくなりそうなもんだけど非公式のツール相手にそこまでやれるもんなんか、みたいな
Rubyの開発方針とか詳しくないので、本体には入ってないけど実質公式みたいなもんだからいい、みたいなのもありそうではあるけど

終わりに

まだ実装を書いておらず、ほぼツールチェイン周りへの感想なのだけど、それでこれだけ出てくるので中々に前途多難を感じる
CIとか組み込んで実際の開発体制に組み込めるか?という点や型の解析周りでの感想は追々やっていけたらなと

参考資料・関連リンク

RBS Railsを使ってRailsアプリケーションにSteepを導入する - pockestrap

GitHub - soutaro/steep-vscode: VSCode extension for Steep

Rubyで型チェック!動かして理解するRBS入門 〜サンプルコードでわかる!Ruby 3.0の主な新機能と変更点 Part 1〜 - Qiita

rbs/syntax.md at master · ruby/rbs · GitHub

Ruby 3の静的解析機能のRBS、TypeProf、Steep、Sorbetの関係についてのノート - クックパッド開発者ブログ

Ruby 3 の静的解析ツール TypeProf の使い方 - クックパッド開発者ブログ