Go言語の思想とエウレカでの5年間の活用

kaneshin
Eureka Engineering
Published in
14 min readDec 19, 2019

--

Original Gopher by Renée French

この記事は Go Advent Calendar 2019 19日目の記事です。

こんにちは、こんばんは。CTO の kaneshin です。エンジニア組織のマネジメントに多く時間を割いていますが、技術的な方面では Go と GCP を掛け合わせて Nature Remo + Go + Cloud Functions + BQ を駆使して、部屋の温度・湿度・照度や人体センターの検知を趣味で少しずつ開発しています。

クラウドサービスをはじめとしたマネージドサービスが主流な界隈にとって、今までアプリケーションの責務として実装していたところをマネージドサービスに責務を委譲することができたりするので、アプリケーションを複雑に実装しなくて済むようになっていますし、保守・運用の観点からもそのような設計方針をよく目につくようになりました。

例えばバッチ処理でデータを ETL 処理の設計を責務分割するのは良い例でしょう。

Data Transformation with Cloud Dataflow // https://cloud.google.com/dataflow/

このようにして、ひとつのアプリケーションで様々な責務を負わない、システムの設計をしてシンプルにしていくことが継続的開発から迅速に価値が提供できる基盤となると考えています。

エウレカにおけるGo言語

エウレカでは Pairs と Pairs Engage の事業のバックエンドが提供する Web API でGo言語を活用しています。

2015年からメインでGo言語を活用をし始めました。一般的な企業では局所的な Web API のアプリケーション開発に使って徐々に会社内に浸透させると思いますが、エウレカではメイン事業の Pairs のコードベースのスクラッチ開発として、当時 PHP で書かれていた Pairs を一気にリプレースを行うことをしていました。

2015年当時はGoを使っているソースコードをみると嬉しくなっていました

2015年は Go の情報が全然存在しなく、社内でナレッジを溜めるのに非常に苦労をしたことを覚えています。
毎日のようにリファクタリングを行い、毎週末にGo を書いているエンジニアで設計方針を協議していました。

Switching to a monorepo

今でこそ、Uber がモノレポにした話とかが GopherCon で聞くことができますが、当時はそういった話が全くなかったので『Google はモノレポでソースコードを管理しているらしいから、分散しているリポジトリを統合しよう』と話して統合したことも記憶に残っています。

モノレポにすると、コードの整合性であったり、コードレビューの効率性の向上につながることがあります。

Goodbye ETL 👋

エウレカでは、冒頭にお話した Dataflow の ETL を途中まで開発していました。データを大量に処理するために goroutine であったり、開発の効率性のために60%を go generate で生成したコードを使用するようにしていました。しかし、結局は日の目をみることはありませんでしたが、このときにGoやマネージドサービスを活用した全体を踏まえた設計思想というのが自分のなかに落とし込まれてきたなと感じます。

2019年の開発について

2019年は2015〜2017年頃と比較して、いまはAPIチームが主導しているので Pairs の開発はチームの方が書いたものをぜひご覧ください。

これは Pairs Engage の開発初期から使用しているライブラリなどを紹介しています。これから開発を始めようと思う方はぜひお読みいただけると嬉しいです。

また、APIチームのあゆみとして、チームの責任者がチームの動きを書いているので合わせて参照していただけると理解が進むと思います。

Go言語の思想 based on UNIX哲学

Gopher

Go is an open source programming language that makes it easy to build simple, reliable, and efficient software.

Go は Google によって開発されたことは有名ですが、なぜ Google は Go (のような設計のプログラミング言語)が必要だったのかという問いに答えられる人はあまりいません。Go が開発された背景については Go at Google に記載されています。

The Go programming language was conceived in late 2007 as an answer to some of the problems we were seeing developing software infrastructure at Google. The computing landscape today is almost unrelated to the environment in which the languages being used, mostly C++, Java, and Python, had been created. The problems introduced by multicore processors, networked systems, massive computation clusters, and the web programming model were being worked around rather than addressed head-on. Moreover, the scale has changed: today’s server programs comprise tens of millions of lines of code, are worked on by hundreds or even thousands of programmers, and are updated literally every day. To make matters worse, build times, even on large compilation clusters, have stretched to many minutes, even hours.

Go was designed and developed to make working in this environment more productive. Besides its better-known aspects such as built-in concurrency and garbage collection, Go’s design considerations include rigorous dependency management, the adaptability of software architecture as systems grow, and robustness across the boundaries between components.

Google ではソフトウェアの開発やさまざまな環境下で増え続ける問題への対処のために開発されたと書かれていたり、また、開発の利便性を捨てて、大規模ソフトウェアの問題に対処することにフォーカスをしています。

つまり、Go は開発のしやすさはもちろんありますが、大規模ソフトウェア開発にまつわる問題を解決するために開発されたといえるでしょう。そのため、プログラミング言語を深く探求する人には言語仕様上、物足りなさを感じると思います。Go は問題解決のために作られたプログラミング言語ということが思想としてあります。

拙作ですが、ここの章に書いてある一部を抜き出して紹介します。この本は Twitter で DM いただければ無償で提供していますが、年末年始にこのBOOTHにある本をアップデートする予定です。

UNIX哲学

プログラミングをしている人ならば、UNIX哲学という単語は一度は聞いたことがあると思います。UNIX哲学では、プログラムやソフトウェア開発における、文化的な規範や哲学的なアプローチの集合であり、UNIXやソフトウェアの開発者たちの経験に基づいて創出されたものです。

Goを開発した方たちは、UNIXやC言語の開発者でもあるため、彼らが積み重ねてきた成功や失敗の経験を活かしています。それらを言語化されたGoが暗黙的にUNIX哲学にも結びついていると筆者は考えています。これから、ふたつのUNIX哲学をもとに、どのようにGoへ活かしていくかを解説します。

マキルロイのUNIX哲学

マルコム・ダグラス・マキルロイ (Malcolm Douglas McIlroy) は、UNIX創始者の一人であり、プロセス間通信を標準入出力を介して接続するパイプの発明者でもあります。マキルロイはUNIX哲学をつぎのように形にしています。

これがUNIXの哲学である。

一つのことを行い、またそれをうまくやるプログラムを書け。
協調して動くプログラムを書け。
標準入出力(テキスト・ストリーム)を扱うプログラムを書け。

標準入出力は普遍的インターフェースなのだ。

“Do One Thing and Do It Well” — ひとつのことを、うまくやれ — と要約されるこの哲学において、Goでツールを開発するとき、無駄な責務を与えないように開発をします。特に意識しているのはつぎの点です。

  • ひとつの責務に集中させる
    プログラムをひとつの責務に集中させていれば複雑にならず、直感的にそのプログラムを使用することが可能です。たとえば、パッケージやコマンドラインツールにおいて、クエリやオプション、引数の渡し方によってプログラムの振る舞いを変えるという実装を多々見てきましたが、それを一度許してしまうと、「またひとつ、またひとつ」のようにオプションが増えていき、プログラムが複雑化していきます。
    プログラムの「責務」を最初に定義し、そこからはみ出してしまうこと、つまり、振る舞いを無理に変えてしまうことを避けて開発をすることでプログラムの複雑度を増加させないようにします。これによって、美しい、キレイなコードを保つこともできるでしょう
  • 他のプログラムに連携可能にする
    さて、ひとつの責務に集中させることに成功したら、別のプログラムと連携できる I/F を提供します。ひとつの責務に集中させることは、別の責務については別のプログラムに責任を委譲していることになるため、その責務の受け渡しをスムーズに行う必要があります。
    パッケージでは関数のシグネチャとして、入力となる引数、出力となる戻り値、そして、関数の名前を適切に設計して公開しなければなりません。アンチパターンとして、入力の引数に関数の振る舞いを変えるための Boolean を提供することは避けるべきです。
type Address struct {
HomeTel string
WorkTel string
}
func (a *Address) SetTel(tel string, isHome bool) {
if isHome {
a.HomeTel = tel
} else {
a.WorkTel = tel
}
}

SetTelの第二引数に isHomeという Boolean を渡す必要がありますが、呼び出し側ではtelを設定するだけなのに、なぜ、真偽値が必要になるかがコードを読まないと把握できません。このように、関数名から直感的に使えない I/F を提供するのは避けるべきです。

ガンカーズのUNIX哲学

マイク・ガンカーズ (Mike Gancarz) は、彼自身の経験を踏まえて、次の9つをUNIX哲学として形にしています。

1. 小さいものは美しい。
2. 各プログラムが一つのことをうまくやるようにせよ。
3. できる限り早く原型(プロトタイプ)を作れ。
4. 効率よりも移植しやすさを選べ。
5. 単純なテキストファイルにデータを格納せよ。
6. ソフトウェアを梃子(てこ)として利用せよ。
7. 効率と移植性を高めるためにシェルスクリプトを利用せよ。
8. 拘束的なユーザーインターフェースは作るな。
9. 全てのプログラムはフィルタとして振る舞うようにせよ。

こちらは、「マキルロイのUNIX哲学」と似ているところがありますが、より具体的に書かれていることや、ガンカーズの経験が活かされた哲学になっています。

すべてGoで書かないことも心がける

ガンカーズのUNIX哲学の 4 と 7 を踏まえて、Goで書かなくても実現できる機能は積極的に責務を分割しています。

  • 4. 効率よりも移植しやすさを選べ。
  • 7. 効率と移植性を高めるためにシェルスクリプトを利用せよ。

効率と移植を考えると、バイナリやコードのロジックの最適化、また、パッケージ設計の話に向かってしまう場面もありますが、そうではありません。

Go に慣れてくると、すべてを Go で実装してしまいたくなるのがエンジニアの性質ですが、すでに世の中にあるツールをうまく組み合わせて、最速で問題を解決へ導くのが事業会社にいるエンジニアには必須なスキルです。たとえば、ただ単に Web API を叩くだけのツールを作るのであれば curl とシェルスクリプトで十分に実現が可能です。

「そこ、本当にGoで書く必要ある?」のように自問し、本来必要である責務にのみ集中させるプログラムを記述することで、複雑度を減少させることも重要です。

これに似た話を以前したので、そのスライドも紹介しておきます。

おわりに

効率性や移植性の話をしましたが、大規模システムを継続的に開発していくための考察です。趣味で書くコードはふんだんに Go で書くことを惜しまないで積極的に書きましょう。

趣味でやる設計やコードを効率性を考えて開発してしまうと、良くも悪くもクラウドサービスとの連携になって、いつの間にか Terraform と戯れる時間の方が多くなってしまいます。少しさみしいので Go ですべて実装してしまうというのも忘れたくないなと思います。

Go を書いていて、今年嬉しかったこと

エウレカでは、『かけがえのない人との出会いを生み出し、日本、アジアにデーティングサービス文化を定着させる。』ためにサービス開発を行っています。

今年、Goのコミュニティで知り合った方々から Pairs を介してお付き合いからご結婚までのご報告を頂きましたし、二次会の場にも参加させて乾杯の挨拶などもさせてもらいました。

『Goをエウレカが使っていなければ、Pairsに触れることもなかったのでは?』と本気で思うこともあるので、Go言語で人の人生を変えられたというのは非常に嬉しいです。

人生にあってよかったものを、これからもGo言語で開発していければと思っています。

--

--

kaneshin
Eureka Engineering

Hi, I’m kaneshin. I’m currently working as a software engineer based in Tokyo, Japan.