オブジェクト指向が分からなくなったので、Smalltalk(Pharo)に入門してみた

[PONOS Advent Calendar 2021](https://qiita.com/advent-calendar/2021/ponos)の23日目の記事です。

昨日は @ackyla さんでした。
→ [Laravelのログを一日より早くローテーションさせる](https://qiita.com/ackyla/items/0e134757e7f158934061)


# はじめに

こんにちは。@honeniqです。
ポノスでは情報システム担当とインフラエンジニアを兼任しています。

最近、Twitterのタイムラインにこの記事が流れてきて、じっくり読んでしまいました。
[オブジェクト指向とは何だったのか？](https://ubiteku.oinker.me/2016/05/09/what-is-oo-all-about/)
2016年に書かれたブログではありますが、数年で色褪せるような内容でもないので、一読をお勧めします。

記事中でも触れられていますが、「世間一般のオブジェクト指向は、アラン・ケイが提唱したそれとは別物なのではないか」的な疑問はたびたび耳にします。
また、RubyがSmalltalkの影響を受けていたり、Scratchが当初Smalltalk（Squeak）で作られていたりと、ずっと気になる言語ではありました。

「気になるなら一度やってみよう」と思い、またアドベントカレンダーのネタに困っていたこともあって、とりあえず触ってみることにしました。


# Smalltalkを始める

## 処理系の選択

Smalltalkは一般的なプログラミング言語と違って、実行環境をまるごと含んだ仮想マシンの形式で配布されています。
ちょうどLinuxディストリビューションのような感覚で、いろんな特徴を持ったSmalltalk環境が、それぞれ個別にメンテナンスされているようです。
[Wikipedia](https://ja.wikipedia.org/wiki/Smalltalk)に載っているだけでも20種類以上ありました。

今回は、2021年現在でも活発に開発されていて、かつ日本語情報もありそうな[Pharo](https://pharo.org/)を選択しました。

## Pharoをインストールする

Pharoを使用するには、まずランチャーをインストールし、そこから仮想マシンを立ち上げます。
[Download Pharo](https://pharo.org/download)のページからインストーラがダウンロードできます。

ランチャーが起動できたら、画面左上の「New」ボタンを押して、仮想マシンイメージを作成します。
その際、使用するテンプレートが選択できるのですが、特にこだわりもないので公式の最新安定版である9.0を選びました。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2492/3e5a42c7-6156-a4f0-8e11-249e06e0b026.png)

作成したイメージをダブルクリックして、仮想マシンを立ち上げます。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2492/4333fe2a-646d-dcec-da8c-0c7503aa3667.png)

起動直後はこんな感じ。


## チュートリアルを探す

知らないソフトウェアや言語を触るときは、とりあえずチュートリアルからやってみるのが鉄板です。

[smalltalk-user.jp](https://www.smalltalk-users.jp/)のサイトで[Pharo by Example(日本語版)](https://www.smalltalk-users.jp/Home/docs#h.p_ID_34)が紹介されており、内容も良さそうだったのでこれを教本にしようと思いました。
ただ、日本語版が作成されたのが相当昔らしく、現行のPharo 9.0にそのまま適用できない感じだったので、最終的には英語版を使うことになりました。（つらい）

[SquareBracketAssociates/PharoByExample9](https://github.com/SquareBracketAssociates/PharoByExample9)
2021年12月時点でまだWIP（作業中）となっていますが、ちゃんとPharo 9.0対応していました。


## (余談) Pharoの語源について

Pharoってあまり聞き慣れない言葉ですが、古代ギリシャ語で「灯台」を意味しているそうです。（だからロゴに灯台の絵がある）

ん？そういえば・・・🤔

Civilizationシリーズの遺産（七不思議）に、「[ファロス灯台](https://ja.wikipedia.org/wiki/%E3%82%A2%E3%83%AC%E3%82%AF%E3%82%B5%E3%83%B3%E3%83%89%E3%83%AA%E3%82%A2%E3%81%AE%E5%A4%A7%E7%81%AF%E5%8F%B0)」ってのがありますね。
この灯台はアレクサンドリア湾岸のファロス島に作られた超でっかい灯台で、鏡で太陽光を反射して船を焼くことができたという、[ソーラ・システム](https://ja.wikipedia.org/wiki/%E3%82%BD%E3%83%BC%E3%83%A9%E3%83%BB%E3%82%B7%E3%82%B9%E3%83%86%E3%83%A0_(%E3%82%AC%E3%83%B3%E3%83%80%E3%83%A0%E3%82%B7%E3%83%AA%E3%83%BC%E3%82%BA))のような逸話があります。

あまりにも有名な灯台だったので、建っていた島の名前が灯台そのものを指す単語になったとか。
勉強になるなぁ。





# Pharoを触ってみた

先ほどご紹介した[SquareBracketAssociates/PharoByExample9](https://github.com/SquareBracketAssociates/PharoByExample9)を読み進めながら、Pharoを触ってみました。
全18章のうち、序盤の6章まで進めた状態でこの記事を書いています。

参考までに、各章の見出しを載せておきます。
<details><summary>Pharo By Example 見出し</summary>
1. About this book
2. Getting Started with Pharo
3. A quick tour of Pharo
4. Finding information in Pharo
5. Developing a simple counter
6. A first application
7. Publishing and packaging your first Pharo project
8. Syntax in a nutshell
9. Understanding message syntax
10. The Pharo object model
11. Traits: reusable class fragments
12. SUnit: Tests in Pharo
13. Basic classes
14. Collections
15. Streams
16. Morphic
17. Classes and metaclasses
18. Reflection
</details>

## ここまでで学んだこと

> 1. About this book
2. Getting Started with Pharo
3. A quick tour of Pharo
4. Finding information in Pharo

1〜4章では、Pharoに搭載された各機能の使い方を学びます。
REPLやクラスブラウザ、デバッガなどの機能が最初から用意されていて、初見のIDEと同じくらいには覚えることがあります。
ここでは駆け足で全体像を掴みつつ、各機能をとりあえず触ってみる程度。

> 5. Developing a simple counter
6. A first application

5・6章から、ようやく開発チュートリアルが始まります。
5章で簡単なカウンター（インクリメントしてデクリメントして現在の数字が取れるやつ）を作りつつ、Gitでのソース管理やTDDの進め方を学び。
6章では、パズルゲーム（LightsOut[^LightsOut]）を題材に、遅延バインディングの良さやデバッグしながらの開発スタイルを身に着けます。

[^LightsOut]: 1995年に日本でも電子玩具として販売されていました。「[ﾃｨｰﾘﾘﾘｰ ﾍﾞﾍﾞｯﾍﾞｯﾍﾞｯ・・・](https://www.youtube.com/watch?v=oL2H1H31G2g)」みたいな起動音が鳴るやつです。


## 開発環境がすごい

ここからは学んだ中で知った凄いところを書いていきます。
それぞれの凄さがSmalltalk環境共通のものなのかPharo特有なのか分からないので、とりあえずPharoの凄いところとして書いています。

### ソースコードが全部見える

環境に取り込んだ全クラスのソースコードが、すべて閲覧可能です。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2492/9ad3bc25-4533-3e5a-60cb-b62166f380cf.png)

対象は文字通り**すべて**で、Pharo実行環境そのもののソースコードも含みます。
単にオープンソースなだけでなく、実行環境の中から直接検索・閲覧できるので、使い勝手が半端ない。


### メソッド探索機能

まずはGifをご覧ください。

![method_finding.gif](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2492/396d4ac1-ba1a-071c-89c3-604f2f63d019.gif)

*お分かりいただけただろうか・・・*

検索窓に``'pharo'.'PHARO'``の形式で書いて検索すると、ドットの左右を**「あるメソッドの適用前・適用後」として扱い、該当するメソッドをサジェスト**してくれます。
「何をやりたいかは分かってるけどメソッド名が分からない」を一撃解決してくれるわけです。

凄くないですか？
凄いよね！


### デバッガ

Pharoのデバッガは、**デバッグ中に実装**して**そのまま実行継続**できます。

![debugger.gif](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2492/b4f28c3a-6211-8023-d8de-947ca4b5bcf0.gif)

解説します。

1. 最初に``LOGame new openInHand``を実行し、LightsOutのゲーム画面を開こうとしています。
2. 直後にエラーで停止してデバッガが開き、停止箇所を示しています。
3. cellsPerSideメソッド[^cellsPerSide]が実装されていないのが原因なので、デバッガの「Create」ボタンを押して新規作成しています。
4. メソッドのテンプレートを書き換えて正しい値を返すようにし、「Proceed」を押すと・・・
5. 停止箇所の続きから再開されて、ゲーム画面が開きました！

普段のプログラミングだと、エラーで停止すると
「はい駄目！ お前はミスしました。やり直し！」
と言われているような気持ちになりますが、Pharoはデバッグもプログラミング行程の一部に組み込まれている感じがして、気分が良いです。

[^cellsPerSide]: ゲーム画面の一辺あたりブロックを何個置くかを返す


# まとめ

他に思ったことを箇条書きで。

* 古い言語だと思っていたけど、使ってみたら凄く新鮮だった
* 構文は癖が強くてまだ馴染めない、けど理解しやすい気はする
* 仮想環境で動くから環境を汚さないし、気軽に試せて良い
* 現時点ではまだ、どうやって現実の課題に使っていけるかが分かってない🤔

Pharo by Example もまだ途中なので、時間を見つけて進めていきたいと思います。


-----

明日は @block  さんです！