Go言語とコード生成

Go言語はコードジェネレータが活きる場面が他の言語と比べて多いということがわかってきた。

Go言語に限らず、近年コードジェネレータの市民権が拡大してきているように感じる。Vue CLIのように、ライブラリ公式のツールがScaffold出力をしてくれるケースも増えてきたし、自動生成されたコードを編集しようとすると警告を出してくれるエディタ/IDEも増えてきた。サーバー間通信でよく使われているgRPCも、Protoから各言語用のコードを生成して使うのが一般的だ。

Go言語でも、go generateというコード生成用の機能/ツールが用意されていたり、こちらの公式ブログにも説明が投稿されるなど、コード生成の活用/促進に力が入っている。

コードジェネレータが使われる一番の目的は、手でコードを書く量を減らすこと、つまりDon’t Repeat Yourselfの実践のためだろう。

DRYの実践が目的なら、共通のコードをライブラリ化する方法を模索するのが手軽だ。しかし、Go言語にはジェネリクスがないため、コードの共通化を実現しにくい場面がしばしある。ジェネリクスがない状態で、色々な型で共通で使える関数を実装しようとすると、interface{}型を使う形になってしまい、型安全性が失われる上にキャスト地獄になってしまう。

参考: GolangのSliceでFilterやMap的なことをやりたい

このようなケースでは、コードジェネレータを使って型ごとに関数/メソッドを用意することで、無理なくセキュアなコードを書くことができる。Go言語ならではの、コードジェネレータが活きる場面だ。

Go言語はソースコード解析の機能が充実している点も、コードジェネレータの普及・促進の後押しになっている。go/parserパッケージを利用すれば、簡単にソースコードの解析できるため、その結果からコードを生成することも容易だ。

参考: ASTを取得する方法を調べる #golang

これによって、アノテーションやコメントからだけでなく、定義されているinterface / structの構造を読んでコードを生成する、といったようなことを簡単に実現できる。

他の言語同様、コードジェネレータの使用には弊害もある。僕自身が実際にこの一年間で体験した問題としても下記のようなものがあった。いずれもGo言語自体に関連はない問題だ。

  1. コードジェネレータの不具合でコードの更新ができなくなる
  2. 生成されたScaffoldの上にコードを書いていった後で、Scaffold部分の実装に問題が見つかったが、もはや全部を再生成することはできなかった
  3. 複数のコードジェネレータを組みあわせて使いたい場面で、ジェネレータが生成するコードの相性が悪い

実際のところ、これらの問題の対応にかかったコストはそこそこあった。しかし、コード生成によってもたらされるメリットはそれ以上に大きかった。コーディング量が減ることに加えて、手で書いた場合に比べて細かい部分の実装が共通化されることの意味は大きい。

コードジェネレータを前提とした最適な設計・開発作業は、手動で全てを書く前提のそれとは異なるので、頭の切り替えが必要だ。コードジェネレータは、導入が効果的な部分とそうでない部分があるが、頭の切り替えのための引き出しを増やすためには、まずは積極的に導入をして知見を得るしかなさそうだ。

Pocket

コメントを残す

メールアドレスが公開されることはありません。 が付いている欄は必須項目です