Reboot kansai.ts #4 に参加しました

Reboot kansai.ts #4 に参加しました
2023.11.27

こんにちは、CX事業本部Delivery部サーバーサイド事業部のmorimorikochanです。

2023/11/22に大阪でReboot kansai.tsが開催されました。
今参加している(していた)ので参加レポートを書きたいと思います。

イベント概要

イベント名 Reboot kansai.ts #4
日時 2021/11/22 19:25〜
場所 サイボウズ大阪オフィス
URL https://kansaits.connpass.com/event/299545/

イベントでは、5人の方からTypeScriptに関する発表がありました。
それぞれの発表について発表資料と合わせて私のざっくりした要約と個人の感想を書いていきます。
ざっくりした要約については発表を聞きながら記述しており、発表資料との整合性を正確にとっておりませんので、一部間違っている可能性があることにご留意ください。
また、主催者の方からイベントの内容を記事にすることについてはあらかじめ了承をいただいています。

1. FizzBuzzで学ぶOCP

nkgrnkgrさんによる発表がありました。
OCPとはopen/closed principleの略で日本語では開放/閉鎖原則と呼ばれる原則なのですが、それをFizzBuzzに適用した例を見ていってOCPを学ぶ、という内容でした。

ざっくりした要約

  • シンプルに実装するFizzBuzzでは、全ての処理を1つの関数に押し込めて実装することになる
  • OCPを適用すると、仕様変更に強くなる
  • どうやって適用するか?
    • 仕様の本質を見る
    • 例えば、FizzBuzzの仕様の本質とはこれら
      • 1.整数を入力すると文字を返す
      • 2.任意の変換ルールを複数定義
      • 3.変換ルールは何らかの判定条件
    • 変換ルールを表すRule, 判定処理を表すMatch, 変換処理を表すApply, 変換ルールの適用順序を表すRULE_SETSというような概念が見えてくる
  • こうすることで、ルールの中身が変わったり、ルールが新たにされても影響範囲が最小限になる。
  • この考え方は色んな問題に適用が可能
    • HTML,JSON, CSVそれぞれのパーサーを作る場合など

感想

本題とは少しズレますが、実装に入る前に仕様の本質を見極めて概念に名前をつける、という行為がとても良いことだなと感じました。
実装しながら適宜重要な概念を見つけて、それに名前をつけることもできなくはないですしたまにやってしまうのですが、概念が不足していたりアンバランスな概念になったりすることがよく発生してしまうなぁと反省しました。これを防ぐために、実装に入る前に仕様の本質を見極める、ということはとても大切だと感じました。

また、OCPやSOLID原則に限らない話ですが、無闇にOCPなどの原則を適用するのではなく、システムの将来性を適切に予測して適用可否を決めることが大事だと感じました。
というのも、SOLID原則はソフトウェアの品質モデルの中で、保守性に大きく関わってくると思いますが、仮に保守する必要が今後100%ないのであれば保守性にコストを注力するよりも他の品質に注力する方が良いかもしれません。(実際のシステムで保守性を全く気にしない、なんてことはほとんどあり得ませんが、少なくとも0か1かではなくグラデーションはあるはずです。)
なのでシステムの将来性を適切に予測して、品質にかけるコストのバランスを取ることが重要だと感じました。また、そうなるとなんの知識もなしにエンジニアだけで正確に予測することは難しいので、そのためにステークホルダーとの密なコミュニケーションが重要になってくるんでしょうね。 (エンタープライズFizzBuzzをふと思い出して気づきました)

2. LangChain.js使ってみた

naoitoさんによる発表がありました。
LangChainとは、大規模言語モデルを利用してアプリケーションを開発するためのフレームワークです。
今回は主に、TypeScriptでLangChainを利用したことを中心に発表されました。

ざっくりした要約

  • LangChainはオープンソースの大規模言語モデルを利用してアプリケーションを開発するためのフレームワーク
    • Javascript/TypeScriptおよびPythonで利用が可能
    • Pythonのスター数はJavascript/TypeScriptの10倍ほど
    • Next.jsのスターターテンプレートがある
      • 今回はこれを使ってみた(公式のデモサイト
      • Chat
      • StructuredOutput
      • Agents
      • Retreval
        • LLMが学習していない情報(コンテキスト)を与え、それを加味させた上で回答を生成できる
        • 会社の情報を加味したり、過去の質問を加味したり
      • Retrieval Agents
  • LangChainを利用するなら、PythonよりTypeScriptを利用した方が良いのではないか
    • データ分析のエンジニアよりもwebアプリケーションエンジニアが主導してLangChainを利用することが多い
    • webアプリケーションエンジニアにとっては型を利用できることは嬉しいから
  • LangChainの中では、Chaints, Agents, Agent Executorなどの概念がある
  • Versel AI SDKを使うと、チャットのUIとしてBlockingUIとStreamingUIが簡単に利用できる
  • LangChain自体にはモデルは内包していないが、Ollamaというローカルで動作するモデルがあり、これを利用することができる

感想

LangChainの名前は聞くものの何ができるのかさっぱりわからなかったのですが、今回の発表を聞いて大枠が理解できた気がします。
Verselはwebアプリケーションの界隈で最近よく名前を聞きますが、Next.jsのスターターテンプレートやVersel AI SDKを提供していたりと、AIの分野に注力しているみたいですね。

3. TypeScriptコンパイラの内側に片足入れる

ryounassoさんによる発表がありました。
主に、TypeScriptコンパイラが内部で行なっている処理フローについて共有されました。

ざっくりした要約

  • 発表のゴールは 1.TypeScriptコンパイラのざっくりした流れがわかるように, 2.それぞれの処理で、メインで動くファイルがわかるように
  • TypeScriptコンパイラのソースコードはmicrosoft/TypeScriptのsrc/compilerディレクトリにある
  • TypeScriptコンパイラがやっていること
    • 字句解析
      • scanner.ts
      • 各文字をトークンに分割する
    • 構文解析
      • parser.ts
      • ツリー状にされ、この時点でASTになる
    • 識別子の結合
      • 変数・関数の宣言や定義を発見
      • スコープを加味
    • 型チェック
      • tsのメイン処理
      • 2.79MBほどのサイズ
    • トランスパイル
      • TSをJSに
      • transformerで処理する
      • それぞれのESのバージョンは別々のtransformerで管理されてる

感想

とても興味深かったです。参加者から「コンパイラのソースコードはTypeScriptだけどそうなると最初はどうやってTypeScriptをコンパイルしているの?」という質問がありましたが、確かにどうなってるんだろう..と感じました。
最初はJavascriptで実装されていて途中からTypeScriptに書き換えたんちゃうかな?と思ってsrc/compilerディレクトリをひたすら過去に遡って調べたんですが、2014年に初めてコミットされた段階からすでにTypeScriptで実装されており、これ以前にどのようにコンパイルされているのかはわかりませんでした。

4. Copying Array Methodsについて

jiko21さんによる発表がありました。
主に、Copying Array Methodsのメリットについて共有されました。

ざっくりした要約

  • Copying Array Methodsは今年になってECMAScriptに入ったproposal
    • 配列に対して非破壊操作ができる
    • TypeScriptバージョン5.2で型情報が追加された
  • 具体的には以下のようなメソッド
    • toReversed()
      • reverse()を非破壊的に実行できる
    • toSpliced()
      • splice()を非破壊的に実行できる
    • with()
      • 配列の特定位置にある単一の要素を書き換えたい
      • 複数書き換えたい場合はtoSpliced()を利用する
  • ただし全てシャローコピー
  • 従来の方法とCopying Array Methodsの間のパフォーマンスの差について
    • 要素数がとても多い状態でコピーしてみた
    • toSpliced()with()はパフォーマンスが改善されそう
  • 型チェック回避芸から解放されることも大きなメリット
    • ReadonlyなArrayをコピーしたい場合が非常に楽になった
    • 型チェック回避芸
      • @ts-ignore
      • spread構文作ったり
      • パフォーマンスが弱い
      • type-festのWritableを使ってreadonlyを打ち消す

感想

やっぱりシャローコピーですよね...他とインタフェース揃えるなら仕方ないのかなと思う反面、ディープコピーも簡単にできるともっと便利になりそうですね
ディープコピーだと昔はJSON.stringify()が早いという話を聞いたことがあるのですが、今はstructuredClone()が主要なブラウザでカバーされているのでこれを使うのがよさそうですね。

また、発表資料から参照はされていませんでしたが、該当のプロポーサルはこちらのようです。
HTMLで提供されているプロポーサルの中身を見ると、プログラムを文章にしたような内部仕様がぎっしり記載されていて驚きました。プロポーサルってこんなふうに丁寧に作成されていくんですね。

5. Honoが良さそう

is_ryoさんによる発表がありました。
主に、Honoの特徴およびHonoを利用してみた感想について共有されていました。

ざっくりした要約

  • HonoはEdge用のシンプルで超高速なフレームワーク
  • 特徴
    • マルチランタイム
    • 様々なミドルウェア・ヘルパー
    • クリーンなAPIと最高級のtsサポート
  • expressに似たフロントエンドのないwebアプリケーションフレームワーク
    • web標準のAPIのみを利用してるから変な依存がない
    • middlewareが豊富
    • JSXのミドルウェアが存在している。これを使えばJSXをレンダリングできるのでSSRが可能

感想

Hono、めちゃくちゃよさそうです!
フロントエンドの動きが単純なシステムを作るときに、単にテンプレートエンジンとしてJSXを利用してサーバーからHTMLを返したい!という場面がよくあるのですが、それを実現するような構成は今までに見つけることができませんでした。
そのようなユースケースにHonoはフィットしており、Honoが大活躍しそうな予感です。
ただ、HonoはJSXを返すだけでフロントエンド側でReactが実行されることはないらしいので、複雑なフロントエンドが必要になった場合の対応が難しいかもしれません。
私はまだNext.jsすら利用したことがない状態なのですが、それよりも先にHonoを利用したい気持ちになりました。

クラスメソッドはHonoの開発を支援しています

クラスメソッドでは様々なOSSの開発を支援しています!

実はその第一弾としてこのHonoのContributorであるYusuke WadaさんにGitHubのSponser機能を通して支援させていただいてます。
私はOSSを開発することよりも利用することの方が圧倒的に多いのでOSSのContributorの方には本当に感謝しています。こういうような支援がもっと増えていくと良いですね🚀

全体的な感想

  • オフラインの勉強会に参加するのは久しぶりなので終始そわそわしてました
  • どれもとても勉強になる内容でした。主催者および発表者の皆様、ありがとうございました!
  • 数日前に勢いだけで申し込みしましたが、次回もぜひ参加したいと思います!