この記事を書いた人
インターノウス株式会社 技術顧問 伊澤 伸
楽天「ぴたっとアド」「ぐるなび」「びあ」などのwebを担当。元株式会社ノボットCTO。
1996年日本オラクル株式会社。2004年ネクストコム株式会社(現三井情報株式会社)に参加後、米国において会社を設立。オフショア開発部隊を率いて「ぐるなび」「びあ」などのWEBリニューアルを担当。
2007年マイクロアドのアドネットーク向けに行動ターゲティング広告システム、不正クリック排除システムを構築。2008年楽天株式会社において、 「ぴたっとアド」の立ち上げを完了させた。2009年株式会社ノボットに参画。CTOとしてシステム基盤を構築し、ノボットバイアウトに貢献。
今から10年ちょっと前の2010年、「staticおじさん」が炎上しました。staticおじさんはネット上のコラムに『実はオブジェクト指向ってしっくりこないんです!』と題し
「メンバー関数をstatic宣言すればインスタンス宣言をしなくてもいい」ということ知ってからは、メンバー関数を従来のファンクションのように使っている。共有変数も、pubulic static宣言していまう。したがってプロパティなんて作らない。
出典:実はオブジェクト指向ってしっくりこないんです!/気分はstatic!|エンジニアライフ
と書いたのです。当時はまだオブジェクト指向プログラミング全盛の時代でしたから、このコラムはボコボコに叩かれました。本当に人格まで否定するようなヒドイ言われようでした。
オブジェクト指向プログラミングの元祖はSimulaだったと言われていますが、一般のプログラマが最初に触れたのはSmalltalk-80ではないでしょうか。Smalltalkではオブジェクトにメッセージをパスすることでオブジェクトに何らかの振舞いをさせていました。こう書くとわかりにくいですがGUIの振る舞いを記述するためと考えるとわかりやすくなります。SmalltalkはGUIを含むOS的な環境を含む言語であって、今では一般的になったGUIの基本動作が初めて定義されました。例えばファイルのアイコンをクリックして、メニューから「開く」を選択します。この動作であるファイルを開くことを指示するわけです。
あるファイルを目的語(object)として開くという動詞(verb)を送る。つまりobjectに対してverbをメッセージとして送ります。objectであるファイルはどのようなパスにあるファイルで、開くにはどうしたらいいか知っているので、結果としてファイルを開いてユーザに見せることができます。GUIのこの方式は当時object-verb方式と呼ばれていました。GUIの方式であるobject-verbのobjectとオブジェクト指向プログラミングでいうobjectが完全に同じものかどうか当時アランケイがどう考えていたかはわかりませんが、僕ら一般のプログラマは明確に区別せず同じようなものとして受け入れていたように思います。GUIとオブジェクト指向プログラミングは渾然一体だったということを覚えていてください。
1. Goの誕生
Goは2009年に発表され、2012年にバージョン1が公開されました。staticおじさんが炎上していた時期とほぼ同時期ですね。Goの起源はGoogleのエンジニアであるRobert Griesemer、ロブ・パイク、ケン・トンプソンによる、新しいプログラミング言語を設計する実験的なプロジェクトから始まり、Googleの本番システムや他の多数の企業やオープンソースプロジェクトでも使用されていることで有名です。
Goは以下のような特徴を持ちます。
- クラスを持たない
- クラスがないので継承もない
- クラスがないのでクラス由来のスコープもない
新しいプログラミング言語を設計する場合、よく知られたプログラミングパラダイムは使えるように設計するのが普通だと思います。しかしGoではオブジェクト指向プログラミングを採用しませんでした。これは意図的に外したと思われます。理由としては、3人の言語設計者すべてが、新しい言語を設計する主なモチベーションとしてC++が好きでないことを共有していたことを述べているからです。
実はSmalltalkは当時から動作させることができるコンピュータが一般的ではなかったので、あまり普及しませんでした。実際の仕事で使われるようになったのはC++が使われるようになってからと記憶しています。C++はメッセージパッシングというような機構を採用せず、クラスメソッドを呼び出す方法を採用しています。このためポリモーフィズムを実現するために継承という概念が取り入れられました。この辺りはC++よりもObjective-Cの方がSmallTalkっぽい匂いがします。
C++からJavaへと受け継がれたクラスと継承を中心とするオブジェクト指向プログラミングは、2012年ごろから批判を受け始めることになります。何段階にも連なる継承のツリーはどこでなんの処理が行われているのか見通しが悪く、思わぬ副作用の温床になるのです。オブジェクト指向プログラミングの悪い点としては、心理的に沢山の継承を使った巨大なツリーを構成した方がカッコいい気がするので、やり過ぎてしまうというところです。
このクラス変数を誰が更新したのか?デバッガでクラスの継承を辿りながら探したことがある人も多いでしょう。また、クラス変数はスコープを持っているので、クラスに沢山のプロパティがある場合、大量のgetter/setterを書くみたいなアホらしい作業も必要になってきます。EclipseとかIDEではgetter/setterを自動生成してくれるみたいなコマンドがあるけど、そうじゃないでしょう。あさっての方向に努力してどうする。
あれ? これってstaticおじさんが言ってることとほぼ同じじゃないか。おじさんはgetter/setterなんて馬鹿馬鹿しいからメンバ変数はpublic staticにすると書いてたぞ。確かにこうすればgetter/setterなんていらないな。おじさんは正しかったのか!
実はstaticおじさんも
オブジェクト指向は、結局のところホントにモノ(オブジェクト)に使われている記法、例えばGUI コンポーネント、データベース、ファイルなどであって、プログラムのアルゴリズムとは無関係のものである。
出典:実はオブジェクト指向ってしっくりこないんです!/気分はstatic!|エンジニアライフ
とさらっと書いてある。そう、SmallTalkでは正しかったオブジェクト指向プログラミングもC++でやや方向性がずれて、そのずれを内包したまま発展してきてしまったのだと思います。その違和感をstaticおじさんはコラムに書き、Googleの開発者はGoを実装することで解消しようとしたのでしょう。
2. Goにおけるオブジェクト指向プログラミング
Goにはクラスも継承もないからオブジェクト指向プログラミングはできないのか、というとそうでもないです。Goでは構造体に他の構造体を埋め込むことができます。
type person struct {
Name string
}
type citizen struct {
Country string
person
}
func (p person) greet() string {
return fmt.Sprintf("Hello, %s", p.Name)
}
上図ではcitizenという構造体にpersonという構造体が埋め込まれています。greetという関数はpersonのメンバ関数として振る舞いますが、citizenに対して呼び出された場合は、citizenに埋め込まれたpersonに対して作用します。
他にもクラス無しでオブジェクト指向プログラミングのメリットを享受する方法は用意されていて、クラスがなくて不便とはならず、それどころかC++やJavaよりも簡潔でメンテナンス性の高いコードを実装することが可能となっています。
3. あらためてGoとは
既存のパラダイムに安易に乗らず、より良い言語を目指して常識を捨ててまったく新しい言語を創造するプロジェクトを運営できるGoogleという企業の基礎体力に改めて強さを感じます。
また、開発者の中にデニス・リッチーと共にCを開発したケン・トンプソンの名前があることに感動します。Goはコンパイラ言語であり、ビルドするとひとつの実行ファイルを生成することができるという単純明快さにCの面影を感じます。
Javaやスクリプト言語では複数のファイルをデプロイするため、ステージングと本番で環境が微妙に異なり、ステージングではうまく動くのに本番で動かなかった苦い経験を持つ方もいるでしょう。Dockerなど仮想環境を使って、より複雑にして問題を解決するより、実行環境がひとつのファイルにまとまるほうが美しい解決方法だと感じます。
4. Goの案件
Go案件については増えてきていますが、RailsやPHPに比べると圧倒的に少ない印象があります。
これまでずっと書いてきたように少し玄人向けの言語のような印象ですね。
なので、コロナ前と後でも市場的に大きく変わったということはありません。
Goは比較的技術力が高く、経営陣に技術選定を任せられたエンジニアが自分で使いたいために使っている印象があります。後にその方が離任されGoの人材を探すのに困難している企業を多く見ます。
面接の際のアピール度を考えると、完全なスタートアップ企業などで働いていきたい方であればメインで学習することをお勧めしますが、RailsやLaravelなどをメイン技術として、Goも少し触りましたという形のほうが、技術も好きなんだなという印象を持たせる意味でもいいのかなと思います。