Elixir/Erlang の最重要コンセプトは「並行指向プログラミング」である、というのは既に書いた通りなのだが、この並行指向プログラミングを可能にする、いわゆる「軽量プロセス」がどのように実現されているのかという情報については、Erlang VM のソースコード以外にまとまった情報はなかなか無いようである。
インクリメンタル開発の落とし穴を避けるためには、アジャイル以前の RUP や UP で提案されていたのと同じように、インクリメンタルとイテレーティブを巧く組み合わせようという話になる(実際には意識せずともそうならざるを得ないが)。そのための手法として、ユーザーストーリーをフィーチャーごとに書くだけでなく、一つのフィーチャーをイテレーティブに発展させるためにストーリーを三枚のカードに分けて書くという方法が提案されている。
『TDD再考』では、Ruby on Rails 開発者の David Heinemeier Hansson 氏が——先ほど導入した言葉を使って説明すれば——開発者視点凝集よりもユーザー視点凝集を重視すべきだという主張を展開していることを紹介した。TDDのような手法を使ってプログラムをデザインすると、ミクロなレベルではどうしても開発者視点に引っ張られて、結果的にユーザー視点凝集よりも開発者視点凝集を優先してしまうというのがDHH氏によるTDD批判の要点である。
プロジェクトに代わって、新たなモデルとして提案されているのが「継続的な変更の流れ(Continuous stream of change)」あるいは「流れ作業生産(Flow production)」と呼ばれるものだ。「流れ作業」というと、アジャイルが目の敵にしていたテイラリズムを想像してしまうが、ここでのフォーカスは顧客価値に基づく小さな変更を継続的に行うことにある。リーンの「かんばん」などはこのモデルに近い。
この価値の問題については、以前「我々は何のためにソフトウェアを開発するのか?」という記事の中でも取り上げた。その中で、Ron Jeffries氏による価値の定義「Value is what you want(価値とはあなたが欲しいもの)」を紹介した。価値を突き詰めれば、経済の問題だと考える人も多いだろうし、あるいは文学の問題だと思う人もいるかもしれない。
この気づきの有無は、この話の前に出てくる、marketing (or sales) people と product people の話題にも関係している。ジョン・スカリー氏はペプシコーラのプロモーションで大成功を納めた人物だ。この分野の人物が craftmanship やプロダクト開発の魔法を理解するのはなかなか難しいのではないかと想像できる。これら職能間の断絶は深く、2016年の今でも、プロダクト開発におけるアイデアの重要性について疑う人はそれほど多くないように見える。
ジョブズ氏のインタビューから15年以上経った2012年、似たようなことを主張している記事を見かけた。アメリカを拠点とするコンピュータ科学分野の国際学会 ACM(Association for Computing Machinery)の機関誌「Communications of the ACM」に掲載された「The idea idea」という記事である。
このような考え方は、さらにクリエイティブな領域に行くとそれほど珍しい話ではなくなる。世界的な小説家であるスティーヴン・キング(Stephen King)氏は、彼の作家人生を記した自伝的著書「On Writing: A Memoir of the Craft」の中で、自身の興味深い小説技法について説明している。
I distrust plot for two reasons: first, because our lives are largely plotless, even when you add in all our reasonable precautions and careful planning; and second, because I believe plotting and the spontaneity of real creation aren’t compatible … I want you to understand that my basic belief about the making of stories is that they pretty much make themselves. The job of the writer is to give them a place to grow (and to transcribe them, of course). (p.159)
I told the interviewer (Mark Singer) that I believed stories are found things, like fossils in the ground, he said that he didn’t believe me. I replied that that was fine, as long as he believed that I believe it. And I do. … Stories are relics, part of an undiscovered preexisting world. The writer’s job is to use the tools in his or her toolbox to get as much of each one out of the ground intact as possible. (p.160)
When and where was the term “object-oriented” used first?
At Utah sometime after Nov 66 when, influenced by Sketchpad, Simula, the design for the ARPAnet, the Burroughs B5000, and my background in Biology and Mathematics, I thought of an architecture for programming. It was probably in 1967 when someone asked me what I was doing, and I said: “It’s object-oriented programming“. – Dr. Alan Kay on the Meaning of “Object-Oriented Programming” (強調は筆者)
そのアラン・ケイ氏によれば、オブジェクト指向で最も重要なのは「メッセージング」なのだと言う。
Smalltalk is not only NOT its syntax or the class library, it is not even about classes. I’m sorry that I long ago coined the term “objects” for this topic because it gets many people to focus on the lesser idea.
The big idea is “messaging” – that is what the kernal of Smalltalk/Squeak is all about – Alan Kay On Messaging (強調は筆者)
Versions of Smalltalk before Smalltalk-80 were still largely based on the (asynchronous, unidirectional) ActorsModel of computation, but with Smalltalk-80, the developers of SmalltalkLanguage switched entirely to the (synchronous, bidirectional) procedural model, while misleadingly retaining the ActorsModel terminology (such as “messages” for what essentially are procedure calls rather than one-way notifications). – Alan Kays Definition Of Object Oriented
出来るだけ多くのことを「work in progress」として扱うことによって進化してきた Smalltalk は、ある段階からあらゆることを決定し固定化したがる人たちによって不毛な議論が繰り返され、その結果、進歩が停滞しているとケイ氏は苛立ちを見せていた。この「work in progress」の考え方は、21世紀になってから普及したアジャイルの考え方そのものである。アジャイルはオブジェクト指向のコミュニティが生み出したものであるが、その考え方の源流はオブジェクト指向の始まりから既に埋め込まれていた。
One of the things I should have mentioned is that there were two main paths that were catalysed by Simula. The early one (just by accident) was the bio/net non-data-procedure route that I took. The other one, which came a little later as an object of study was abstract data types, and this got much more play. – Dr. Alan Kay on the Meaning of “Object-Oriented Programming”
ケイ氏の考えとしては、抽象データ型系列の C++ はオブジェクト指向としては認識していないようであるが(「”I invented the term object-oriented, and I can tell you that C++ wasn’t what I had in mind”」)、型システムそのものについて否定的に見ているわけではないようである。
パーソナルコンピューティングの主題は、コンピュータを使っていかに人間の能力を高めるか(「Amplify human reach」)ということであったが、これは言い換えれば「クリエイティビティ(創造性)」の追求である。ケイ氏が最も熱心に取り組んでいたのはコンピュータを使った子供の教育であった。オブジェクト指向プログラミングを子供に教えることによって、ソフトウェアを自身の問題に合わせて自在に変更出来るようにし、より高い問題解決能力を獲得させることを目指した。
この教育プロジェクトの試行錯誤によって得られた知見には大変興味深いものが多い。例えば、Smalltalk がクリエイティビティに寄与する一つの根拠として、より少ない原則で多くを表現できるというものがある。有名な「Everything is an object」というやつである。後のケイ氏であれば「Everything is a message」と言ったかもしれない(そのようなプログラミング言語が実際に存在する)。この全てがオブジェクトであるという原則と、大きなシステム(オブジェクト)は小さなシステム(オブジェクト)の組み合わせで作られるという「再帰的デザイン」によって、どんな複雑なシステムをデザインするときでも、覚えなくてはならない原則は少なくて済むようになる。さらに Smalltalk において重要なのは、システムを使うという行為と作るという行為が全く同じになるということである。システムを使うときと全く同じ操作で、その延長線上でシステム自体を変更することができる。このように、導入において覚えることが少なくて済む、そしてその少ない道具立ててであらゆることが表現できるという枠組みが、子供の教育にとって重要であることは想像に難くない。しかし、実際に試してみて分かったことは、あるオブジェクトにメッセージを送るという1ステップの変更については小さな子供でも理解することが出来るが、複数ステップの変更を組み合わせないと解決できないような問題になると、それがほんの2、3ステップだったとしても極めて難しくなってしまうということだった。これは子供だけでなく、プログラミング経験のない大人でも似たような現象が見られたようである。初歩の問題は容易にクリアできるが、問題が複雑化すると、それがプログラマから見たら些細だと思われる問題でも全く歯が立たなくなる。これは今で言うプログラムデザインの問題である。このデザインの教育に対応するためにケイ氏の同僚である Adele Goldberg 氏が「design templates」という仕組みを考案した。これはぼんやりとしたデザインのアイデアとプログラムによる実例の中間に位置する道具立ててで、今で言うところのデザインパターンやフレームワークに相当するものである。
ケイ氏は、このような大きなビジョンを掲げることの重要性について、そして出来るだけ多くを「work in progress」にすることの重要性について繰り返し語っているが、それはいかに多くの技術者や専門家が手段に埋没し、そして宗教論争に明け暮れているかということに対しての警鐘にもなっている。
スティーブ・ジョブズ
「The Early History Of Smalltalk」の一つのハイライトは、1979年、ケイ氏の勤めるパロアルト研究所(PARC)に、あのスティーブ・ジョブズ氏が訪れる場面である。当時のジョブズ氏は77年にアップルコンピュータを設立したばかりで、次世代のパーソナルコンピュータを生み出そうと Lisa プロジェクトを立ち上げていたが、決定的なアイデアがなく模索中の段階であった。ケイ氏は、PARCに訪れたアップルの面々に対して、ALTOというパーソナルコンピュータ試作機のデモを行う。ALTO には Smalltalk による OS が搭載されており、その上ではウィンドウベースのGUIが動いていた。
Xerox Alto Computer
そのデモの最中、ジョブズ氏は、試作機で動いていたウィンドウシステムのスクロールをもっと滑らかな方式に変更出来ないかと指摘し、開発者の一人である Dan Ingalls 氏がその場で修正して訪問者を驚かせたという場面が紹介されている。Smalltalk 環境の強力さが垣間見えるエピソードである。
このインタビューの中で、1995年当時、今後10年間で最も重要だと思われるテクノロジーとして、ジョブズ氏はオブジェクト(指向)と Web の二つを挙げている。
そして現在
オブジェクト指向についてその起源から検討してみたが、この歴史を前提に改めて考えてみると、昨今言われる「オブジェクト指向から関数型へ」という話が大分狭い領域の話であることに気づかされる。モジュールシステムの進化という観点から言えば、関数型プログラミングが有効である場面が増えているのは疑いようがない。しかし、より大きなスコープで考えるとオブジェクト指向の考え方は依然として重要であり、将来的には、以前紹介した「Functional in the small, OO in the large」という形で適材適所に住み分けることになるのではないだろうか。
David Heinemeier Hansson氏の「TDD is dead」は、アジャイル界隈に醸成されていたある種の信仰を、過激な論調で批判したことによって大変なセンセーションを巻き起こした。強い言葉に対しては、やはり感情的な反応が多くなる。中には坊主憎けりゃ袈裟まで憎いという感じで、TDDを超えてRailsの設計思想を批判する人まで現れたが、「TDD is dead」を受けて行われた「Is TDD Dead?」という歴史的な会談の内容を見るに、DHH氏の発言は、規律(信仰)に対する単純なカウンターなどではなく、そこにはプログラムデザインについての重要な論点が含まれているように思える。
Railsのようなフレームワークには、モデルとデータベースを密結合させた Active Record という仕組みがある。アプリケーションロジックを担当するコントローラは、この Active Record を直接操作するため、そのままだとデータベースにアクセスせずにアプリケーションロジックをテストする事は出来ない。そこでまずはアプリケーションロジックをコントローラから切り離して Action Runner というオブジェクトに移してフレームワークへの依存をなくし、その上で Action Runner は Repository という間接層を経由して Active Record の機能にアクセスするようにする。このようにすればアプリケーションロジックを Rails の枠組みに載せる事なくテスト出来るようになるというわけである。
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters. Learn more about bidirectional Unicode characters
$ mix help | grep release
mix release # Build a release for the current mix application
mix release.clean # Clean up any release-related files
mix release.plugins # View information about active release plugins
実は、今回の自動化環境を作る際の苦労の多くは、この exrm に起因している。現時点ではまだ version 1.0 がリリースされてないので、成熟してないが故の制限がいくつかあった:
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters. Learn more about bidirectional Unicode characters
設定内容をElixirコードで表現出来るので、単なる値だけではなく式などを指定することも出来る。Elixirのコーディングに慣れているプログラマーにとってはとても便利な仕組みであるが、 Elixirに慣れていないオペレーターがコンフィグレーションを行う場合、あまり理解しやすい形式とは言えないかもしれない。この問題に対処するためのツールが Conform である。
:conform を deps に追加して、mix do deps.get, compile すれば、mixに以下のような関連タスクが追加される。
$ mix help | grep conform
mix conform.configure # Create a .conf file from schema and project config
mix conform.effective # Print the effective configuration for the current project
mix conform.new # Create a new .schema.exs file for configuring your app with conform
Conformを利用して、アプリケーション起動時(あるいはアップグレード時)に設定を適用する
さて、今回のプロジェクトで Conform を採用したのは Key-Value 形式の設定ファイルが欲しいからではなく、exrm のセクションで言及した、設定内容を実行時に決定出来ない(環境変数を利用出来ない)問題に対処するためである。
最終手段として、デプロイ時にリリースパッケージ内にある sys.config を直接編集してしまえば良いのだが、そのままでデプロイできるパッケージ(*.tar.gz形式のアーカイブ)を展開して処理するのには抵抗があった。色々と調べ回って Conform の設定ファイルはリリースパッケージと同じディレクトリに置いておけば起動時に適用されることが分かり、最終的にこの Conform を利用する方法に辿り着いた。
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters. Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters. Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters. Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters. Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters. Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters. Learn more about bidirectional Unicode characters
パッケージリリースの処理にもあるように、ビルドの際、CircleCIからAWS上の各種リソースにアクセスする必要がある。そのために必要な最低限の権限を付与した IAM User を作成し、CircleCIのプロジェクトに設定しておく。
以下は今回のプロジェクト用に作成した、リリース・デプロイ担当の IAM User に付与したポリシー(Inline Policies)の例である:
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters. Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters. Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters. Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters. Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters. Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters. Learn more about bidirectional Unicode characters
そして興味深いのは、オブジェクト指向の上に関数型の仕組みを乗っけるのは止めた方が良いという主張だ。この記事を書いた John D. Cook 氏は、関数型のメリットを享受したいのなら、まずは関数型だけに集中し、プログラムの大きなパーツ(モジュールなど)を管理する時にオブジェクト指向的な枠組みを利用すれば良いのではないかと書く(「functional in the small, OO in the large」)。
James Hague 氏は、100%純粋な関数型を実現するのは非現実的であり、大体85%ぐらいを目指せばいいのではないかと主張する。そして、残りの15%は注意深く分離してコードの中に分散しないようにすべきであると。
副作用がある部分を切り離すデザインは、Phoenix Frameworkで採用されているデータアクセスのフレームワーク、Ectoの中にも見られた。Ectoでは副作用のない Model と、副作用を担当する Repository を分けるという、いわゆる Repositoryパターンが採用されている。Railsの Active Record が Model 自身に副作用を内包するのとは対照的である。
Dave Thomas氏は度々このブログにも登場しているが、『達人プログラマー』の著者であり、アジャイルソフトウェア開発宣言の発起人の一人でもある。近年はRubyの人という感じであったが、ElixirにRuby以来の衝撃を受けて、この「Programming Elixir」を執筆するに至ったとのこと。
defmodule Chain do
def counter(next_pid) do
receive do
n -> send next_pid, n + 1
end
end
def create_processes(n) do
last = Enum.reduce 1..n, self,
fn (_, send_to) -> spawn(Chain, :counter, [send_to]) end
send last, 0
receive do
final_answer when is_integer(final_answer) ->
"Result is #{inspect(final_answer)}"
end
end
def run(n) do
IO.puts inspect :timer.tc(Chain, :create_processes, [n])
end
end
Elixirを作ったのは、Ruby on Rails開発チームのコアメンバーである Jose Valim氏である。だからなのか、Elixirはいわゆる関数型言語であるが、Scalaのようなハードコアな感じはない。言語のシンタックスを見る限り、もっと気軽に関数型プログラミングを始められそうな親しみやすさが漂っている。更に言えば、Railsコミュニティとその周辺でよく聞かれる「一番大事なのは目の前の仕事を片付けることである」という哲学を踏襲しているように感じられる。
アメリカのメッセンジャーアプリの最大手 Whatsappでは、一つのサーバーで200万同時接続を実現するシステムをErlangで実装しているという。高度なリアルタイム性と大量の同時接続を要求するオンラインゲームの世界でもErlangは活躍しており、Call of Duty や Game of War といったゲームで利用されているということだ。
さらに今回の記事で紹介されているのは、Ruby on Rails の Controller や Active Record といったパーツを他のレイヤーに依存させずにユニットテストするためにこの Hexagonal architecture を導入するという例で、これは完全にやり過ぎであると、DHH氏は批判しているわけである。
それぞれのレイヤーを単独でテスト出来るようにするため、Controller からは直接 Active Record にアクセスさせずに Repositoryパターンを経由するようにし、Controller内のロジックは Commandパターンとして切り出す。つまり、ロジックを Rails に依存しないモジュールに配置して、それらを Rails から切り離して高速にテストできるようにするためのテクニックである。
世の中が「規模の経済(economies of scale)」に向かって邁進して行く中、Strickler氏以外にも、その価値観に疑義を呈する人たちがいる。その中でも有名なのが、このブログの連載「TDD再考」に度々登場する Ruby on Railsの作者、David Heinemeier Hansson (DHH) 氏である。
この「TDD再考」シリーズの第三回で「TDD is dead」に対する Kent Beck氏の反応を紹介したが、今回は Martin Fowler氏の反応について検討してみたい。この後、David Heinemeier Hansson, Kent Beck, Martin Fowlerの三者は「Is TDD Dead?」という対談を展開して行くことになる。
「TDD is dead」が公開されて激しく燃え上がっている中、Fowler氏はまず「UnitTest」というタイトルの記事を自身のサイトに投稿している。
この記事の中でFowler氏は、DHH氏の記事の内容には直接触れずに、そもそもユニットテストの定義って何なのだろうという話を展開している。それは、DHH氏やJames O Coplien氏の批判の矛先がユニットテスト(の価値)にあり、議論に先立ってまずユニットテストってそもそも何なの? という部分をはっきりさせておきたいということがあったのだろう。
Indeed this lack of isolation was one of the reasons we were criticized for our use of the term “unit testing”. I think that the term “unit testing” is appropriate because these tests are tests of the behavior of a single unit. We write the tests assuming everything other than that unit is working correctly.
これまでたまチームは、Gitのブランチ管理に関しては何も方針を決めておらず(単純に master に push されたものがステージング・本番、双方へのデプロイ可能なバージョンとしてビルドされる)、結果的に Trunk Based Development という、今回の記事で推薦されている、ブランチを極力作らないシンプルな開発モデルになっていたのだが、後述する事情で以下のような Vincent Driessen氏提案のブランチ管理に移行した。
このインターネットによる革命の新たな波がUberやAirbnbといったシェアリング・エコノミーである。シェアリング・エコノミーによって生まれた新しい経済構造を、O’Reilly氏は「個人のフランチャイズ化(The franchise of one)」と呼ぶ。テクノロジーの進歩によって、フランチャイズの末端を構成していた小さな事業者のネットワークは、自身のリソース(Uberでは車とその運転、Airbnbでは家)をパートタイムで提供する「個人」のネットワークに置き換わった。
この状況を打開するため、Hunt氏は「GROWS™」という手法を提案している。GROWSは「GRowing Real-World Oriented Working Systems」の略語にもなっており、これは商標として扱われている。誰でも自由に使えるようにしてその本来の意味を歪められてしまったアジャイルの轍を踏まないように、というのが商標にした理由らしい。
さて、言葉を占有して解釈を限定させようという方法は、本当に良い方法だろうか? 個人的にはそう思えない。オブジェクト指向やアジャイルという考え方は、本質的には、物事のInsight(見識)を提供してくれるものであって、何らかの手順を踏めばプロジェクトがうまく行くといったような処方箋を与えるものではないと思う。もしそれらの考え方が役に立たなかったのであれば、それは単に受け手側の問題である。自分(の状況)には合わなかったと思って次をあたるべきだ。しかしながら現実には、以前の記事で書いたように、ある考え方が流行るとその周辺をコンサルタントやコンサルティング会社が商機を求めて集まってくる。そこで「○○を使ったらお宅のプロジェクトもうまく行きますよ」という具合に喧伝する。その中でことごとく裏切られた期待が炎上を引き起こし、Andy Hunt氏や James Shore氏のようなコミュニティを代表する人たちが火消しに走らなければならなくなる。この風景はソフトウェア開発産業に限らず、セールスマンが存在する限り、あらゆるところで繰り返されているのだろう。
think of a test that will force you to add the next few lines of production code. This is the hardest part of TDD because the concept of tests driving your code seems backwards, and because it can be difficult to think in small increments. (James Shore: The Art of Agile Development: Test-Driven Development)