この記事はThe Java Baggage: Biggest Bottleneck to Adopt Go in Enterprisesの和訳です。
私はコンサルタントとして、Goのトレーナーとして、システムアーキテクチャーとしてインドで働いています。多くの開発チームがGoを採用してシステムを作っています。
私はエンジニアとして、スタートアップ、中小企業、大企業で働いた経験があります。
いくつかの大企業(全てではないがほとんど多くの企業)での経験を除いて、Goの採用はとても良い経験でした。
私が新人エンジニアのメンタリングを行ったとき、彼らはすぐに経験豊かなエンジニアに負けないくらいGoに慣れていきました。
何故ならばGoはとてもシンプルでミニマムな言語であるからで、Goを導入することはとてもイージーであり、スタートアップにの開発においてはとても利便性が高いからです。
まだ経験の浅いエンジニアにとって優れている点は、プログラミングにおける知識・先入観が少ないと言うことであり、そのため彼らは先輩エンジニアから学んだことを吸収する土壌が整っていると言える。
Javaの先入観がもたらすGo実装における危険な姿勢
私のコンサルティングの経験から言うと、大企業でのメンタリングは困難を伴うことが度々あった。
その主な理由は、彼らのプログラミング経験から来る先入観にあった。
これらのチームはJavaにおける大規模開発の知見があり、彼らはGoをJavaと同じように使おうとし、またJavaアプリでの開発と同じようにGo言語を扱う。
私はGoのinversion of control(IoC) コンテナを探したり、Spring BootのGoバージョンのプロダクトを探したりとするチームを見たことがある。彼らはまだGoの言語の基礎や哲学について何も知らないにも関わらず…。
多くのJavaプログラマ、特に経験の多い方々ほど、初めはGoFのデザインパターン、また大規模開発的システムをGoで目指そうとする。
彼らはJavaで書いてきたコードを元に、正しい書き方をGoで書こうとする。
彼らはプログラム言語の主流に剃ってGoを使用するが、そこにGo言語の特徴に対する理解はない。
彼らはGoに対する熱意がないままGoを使用している。
彼らの組織においては、どこかの第三者もしくはクライアントによってGoの採用が決めたのかもしれない。
Goに対する良い噂を聞いた誰かが、プロジェクトに使ってみたかったのかもしれない。
そういうことである。何か新しいものを適応したいと言うだけのために採用されたのだろう。
これはとても危険なことである。
技術選定者はGoを良い理由から選んだのかもしれないが、大きなチームで新しい言語を導入する際は、その言語の魂の理解がない限り、たくさんの問題を産み出してしまう。
私がプログラミングワークショップを開催した際も、幾らかの人々(振る舞いに問題がある人はほとんどいかなったが)はGoの慣習にしたがってコードを書くことに対して意識が低かった。
彼らはJavaのやり方でGoを書きたがっている。
もしあなたがJavaと同じようなものをGoに期待しているとしたら、それは大問題だ。
Goのユーザー定義型をJavaのように捉えることはたくさんの問題を発生させる。
Goのインターフェースは暗黙的に実装されており、これはとても良いものであるが、インターフェースは明示的に書かれるべきだというJavaの先入観を持っている場合は問題に感じるだろう。
もしJavaの代替としてGoを採用しているのであれば間違った適用である。ソフトウェアを書く上でそのように考えているのであれば、GoではなくJavaを使用するべきだ。
言語を選択する際は、期待する振る舞いや哲学を考慮した上で、強み(メリット)と弱み(デメリット)を意識するべきだ。
Go哲学の理解
プログラミング言語、ツール、フレームワーク、そしてアーキテクチャーでさえも、全てはある種の問題解決のために存在する。革命的な言語やツールが多く存在し、それらは我々の過去の経験の改善、および問題解決のためのチャレンジの賜物である。そう、新たなものを産み出す時、我々は過去に経験してきた問題を当然考慮する。
この宇宙にある全てのものは進化をし続けている。永続的なものは存在しない。これはソフトウェア開発においても同じだ。諸行無常、万物流転、この世のものは移り変る。
Goはシンプリシティとプラグマティズム(実用主義)を元にデザインされており、言語理論(PLT)やアカデミックな考えについては意識されていない。Go言語をマスターする上で最も大切かことは、初心に返ってGoを書くことである。初心に返り、過去の経験からくる先入観を取り除くことで、多くの発見がいたるところに見つかるはずだ。
6年前に私がGoを導入した時、私は熟練のC#開発者でありアーキテクトであり、マイクロソフトの.NETをベータバージョンから使用していた。
C#や.NETの知識を取り除いてGoに触れた時、この実用的な言語にとても興奮した。
数年間Goでシステムを書いた今、マイクロソフト.NETではとてもオーバーエンジニアリングなことをしていたと、今だから言える。
Goのユーザー定義型とへ並行性の思想は特に刺激的である。
ユーザー定義型において状態と振る舞いは独立しており、状態をstructのbodyに宣言する一方で、振る舞いはレシーバーを使用してfunctionとして書く。
また、Goのインターフェースは暗黙的に実装されている。
実践的な観点から初心に返ってみてみると、Goは従来のオブジェクト指向言語とは異なるという点に関して、すぐに気付くであろう。
Goは従来のオブジェクト指向言語ではないことを忘れないでほしい。
それ故に従来のオブジェクト指向言語のためにデザインされたデザインパターンをGoに適応することを考えると、正しい実装ではないかもしれない。
これまでJavaで書いてきたような従来の多くのパターンをGoに見出そうとしてきたJava開発者をたくさん見てきた。
Goの世界においてパターンを探す時、Goの場合は異なる。Goのもつシンプリシティのため、多少コピー&ペーストが増えるような場面がある。
例としてGo1.13において、Goあジェネリクスをサポートしておらず、これは特定の条件において幾らかのコピー&ペーストを必要とすることになる。シンプリシティ/パフォーマンスと引き換えにジェネリクス機能を失っている。
言語を理解することは、コードを書く以前にとても重要なことだ。
優れたエンジニアリング思想の重要視
新人エンジニアの方にメンタリンじを実施する際、わたしは常に、言語のシンタックスや文法よりも、ソフトウェアエンジニアリングの教義(principle)に集中するよう伝えている。
プログラミング言語は、その文法とセマンティックを用いることでコードを書くためのメカニズムを提供しているにすぎない。
たとえ優れた言語を使用したとしても、優れた知識がなければそれを活かすことはできない。
言語のシンタックスや昨日に縛り付けられている開発者も多く、それは正しいマナーの理解を損なう問題となっている。
「シンタックスに注目するな、それは物事の魂や可能性の理解を妨げてしまう」と私は伝えてきた。
Goのインターフェースを構文上の障害とみなす時、それはGoの魂を見逃している。
だがGoのインターフェースはてスタビリティと拡張性を備えた素晴らしいソフトウェアを書くことを可能とする。
もし、良いエンジニア教義に集中するのであれば、良いコードはどんな言語でも書ける(もちろんその開発思想を理解していれば)。
使用している言語の特性を理解し、ソフトウェアエンジニアリングの教義と結びつけよう。
SOLIDの原則を学ぶことはとても有用であるし、クリーンアーキテクチャベースの構築について学ぶことも大切だ。
あなたがプロダクトに関わるとき、あなたの主要な目標はドメインごとの問題を解決することであり、言語の特性やパターンを活かすことではない。
なので、はじめにドメインごとの問題を噛み砕き、その後に、問題を解決するための特性を持った言語について検討しよう。
あなたがGoを採用するとき、慣習的なGoのコードを書くことによって、SOLID原則・クリーンアーキテクチャを基礎としたソフトウェアを書きましょう
GoをJavaの書き方で書くのであれば、それはあまり効果的ではないので、Javaを使用しましょう。
アプリケーションをGoで書くときは、グローバル変数を使用することは避けましょう。
もしパッケージレベルのフリーな関数を書くときやグローバル変数を書くときは、その代わりにstructを設けてメソッドを追加しましょう。
これにより依存性を切り離すことができ、同時にテスタビリティを向上させます。
最も重要なことはシステムを疎結合にすることであり、そのためにプロパティパラメターやメソッドを通した明示的な依存関係をstructにより定義しましょう。
依存的なロジックは全体の構造から除きましょう。依存関係についてはインターフェースを用いて実装しましょう。