Go
設計
アーキテクチャ


はじめに

Goの良いところは、最低限の文法を知っていればコードを上から順番に読むことで詳細を容易に理解できることです。

文法の中にシンタックスシュガーや特別な省略が許されていないため多様な表現になることはありません。

そのためGoを書ければGoの本体と標準ライブラリを読むことができます。

しかし以下の原因により、これらの利点を守ることが難しくなることがあります。


  • DSL

  • フレームワーク

  • 抽象化

これらは設計として新たな制約を課すことで品質向上や実装を容易にするためのものです。

またこれらを採用する論理立てた 正しい 理由が存在します。


DSL

DSLを提供するツールとして、DIのための wire があります。

GoでDIを実現するためには多くの実装を必要とするため、実装量を減らすためにもDIツールが求められてきました。

これは 正しい です。

しかし一方でDSLはコードを読む人間に言語以上の知識を求めます。

また詳細な挙動をすべて理解して追うことは難しいです。恐らく wire の内部実装をすべて理解して利用している人は少ないでしょう。


フレームワーク

Goの net/httpパッケージは一般的なWebフレームワークに比べて機能が少ないためコードが冗長になります。

そのためWebフレームワークが求められてきました。

これは 正しい です。

しかし一方でWebフレームワークはコードを読む人間に言語以上の知識を求めます。

ときには標準ライブラリのnet/httpとの接続が難しくなることもあります。

また詳細な挙動をすべて理解して追うことは難しいです。恐らく ginecho などの内部実装をすべて理解して利用している人は少ないでしょう。

Webフレームワーク以外にもORマッパーやテスト用のアサーションツールなども同様です。


抽象化

テスタビリティやSOLID原則のために抽象化することがあります。

Clean ArchitectureのInput Port、Output PortやDDDのレイヤードアーキテクチャのRepositoryなどもこれに該当します。

これは 正しい です。

しかし一方で抽象化は本質的なロジック以外のコードが増え、コードの可読性を落とすことがあります。

またどうしても完全な動作を理解しようとしたときは抽象化された先の実装を追う必要がでてきます。


正しさと悪

これらの制約の 正しさ は、正しいため反論をすることは難しいです。

またDSL、フレームワーク、抽象化もGoで実装されているため勉強して理解しないことを とすることが簡単にできます。

しかしこれには毅然として立ち向かう必要があります。


正しさとGo

私は、Goは制約の代わりに読みやすさでコード品質を担保することに比重をおいた言語だと考えています。

例えばJavaでは、検査例外により呼び出し側にエラーハンドリングをしなければいけないという制約を課しました。

Goでは必ずerrorを返すだけです。それを _ で捨てることや受けないこともできてしまうため制約がありません。しかしほとんどの場合はコードレビューで気がつくことができます。

これだけを聞くと、「コードレビューは見逃す可能性があるのだから、正しく設計をすることでコンパイル時に気がつけるようにするべきだ」 となり、Goの姿勢はエンジニアとして正しくないように感じます。

そのため他の言語を主軸に置いている人からの批判がGoではどうしても多くなりがちです。

しかし正しさを求めることは 制約の代わりに読みやすさでコード品質を担保する ということから離れていくことでもあります。

これらを両立してコーディングしていくことがGoを書く上では、他の言語以上に大切になります。


フレームワークを採用しないことが正しいのか

では、フレームワークを採用しないことが正しいのでしょうか?

以下の場合は採用すべきです。


  • 学ぶ範囲を適切に絞れているツールである

  • ツールの価値が学習コスト以上にある

  • 適切な代替手段がない

GRPCは、Protocol Buffersで記述したルールに基づきコードが生成されます。このルールを覚えることは容易です。

またMicroservicesの文脈では、GRPC前提であることが多いため適切な代替手段がありません。

そのため採用するべきです。

と言うことはできますが、他のWebフレームワークなどでも同様の 正しさ を主張することは可能でしょう。

そのため状況と程度の問題であり、最終的にはアーキテクトのセンスに委ねられます。


まとめ

あるGo本体に近いレイヤーでコードを書いている人から、この 正しさ を嫌う意見を聞いたことが、この話を考え始めたきっかけです。

逆に他の言語でWebアプリケーションを書いてきた方は、この 正しさ を好む傾向にあると思います。

私はどちらの意見も間違ってはいないと思います。

ただしインターネット上にはこの 正しさ が溢れており、新しい技術や目の前の課題を解決してくれるツールは素晴らしく見えます。

そこで新しいツールを導入する際には、一度立ち止まりGoとはこのような言語であったということを思い出し、課題設定が正しいかを改めて考え直してみてください。

それを踏まえてプロダクトと組織のことを考え、長期的に負債を生まないように適切な解決手段を提案しなければなりません。

これらのバランスを考え技術選定できることがアーキテクトの実力の見せ所であり、本当のスキルではないでしょうか。


蛇足


  • 今回はDSL、Webフレームワーク、抽象化に対してどのように対応したかを書いていませんが、また別の機会があればそれぞれ別の記事を書こうと思います。その正しさについて別の課題設定をすることで解決しています。

  • この話は別の視点で考えると、読むコストと書くコストのどちらに比重をおくべきかの議論なのかもしれません。