本格的に作り込まれたExercismのトラックには、コンセプト演習とプラクティス演習という2種類の演習があります。この2つは根本的に異なり、うまく補い合う関係にあります。
トラックのコンセプト演習は、特定のプログラミング言語の基礎を形づくる個々のコンセプトを教えるために設計された演習です。こうしたコンセプトが_シラバス_を形づくります。
このドキュメントでは、トラックのシラバスをうまく設計するためのヒントや指針を紹介します。
シラバスの最終的な目標は、学習者が対象の言語で慣用的なコードを無理なく読めて書けるようになることです。
個々のコンセプト演習は、焦点が非常に絞られています。言語のある側面を理解するための、小さく的を絞った一歩であり、それまでに紹介されたコンセプトだけを土台にしています。
その演習を解くことで、学習者はそのコンセプトに慣れていくプロセスを始めます。理解は主に手を動かすことから生まれ、説明から得られることはずっと少ないものです。説明の内容は、演習を解くために必要な考え方を学習者に紹介するためのものです(ファイル名をintroduction.mdにしているのはそのためです)。
学習者には、最初からすべてを理解していなくても、すぐにコードを書き始められるようになってほしいと考えています。そのために、細かい部分はあえて曖昧にし、説明しないこともたくさんあります。できるだけ簡略化し、コードのスタブを用意します。こうすることで、始めるときの認知的負担が減り、知識が身につくための時間と余白が生まれます。このアプローチは、これらのことを知る必要がないと言っているのではなく、まだ知る必要がないと言っているのです。
最初のほうの演習には、慣用的でないコードが含まれることがよくあります。始めたばかりの学習者にとっては言語の大部分がまだ未知で、ほとんどのコンセプトもまだ紹介されていないからです。最初のほうの演習で慣用的でないコードを認めることで、学習者は不慣れな領域で大きな一歩を数歩進むのではなく、慣れた領域で小さな歩みを数多く進めます。その結果、より早く、より少ない抵抗で慣用的なコードの段階にたどり着けるようになります。
演習はツリー構造になっており、頂点にある入門的な演習が出発点になります。後ろの演習では、それより前に教えられたコンセプトを理解していることを前提とするコンセプトを扱います。
他の言語のトラックがどのようにコンセプト演習を組み立てているかを見てみるのも価値があります。他の言語トラックのコンセプト演習の例はこちらで見られます。
とはいえ、他の演習を自分のトラックの出発点として使う場合は、できあがった演習が、自分の言語に存在する形のコンセプトを扱っているかどうか、注意して確かめてください。コンセプトは、微妙に違うこともあれば、根本的に違うこともあります。そもそも他の言語には存在しないコンセプトもあります。
シラバス、ひいてはコンセプトツリーは、その言語に存在するコンセプトを表しているべきです。他のトラックが入れているからという理由だけでコンセプトを入れてはいけません。
中には、既に存在するコンセプトを使って回避することがよくあるために、そのコンセプトを入れたくなる場合もあるでしょう。そうするのではなく、その言語が_実際に_使っているコンセプトを紹介し、そういう場面でそれをどう使うかを説明する演習を追加することを検討してください。
たとえば、Goにはenumがありません。代わりにGoのコンセプトツリーでは定数を紹介し、他の言語でenumを使うような場面で定数をどう使うかを教えます。
遠慮なく助けを求めてください。コードレビューで議論するより、最初に、あるいは演習に取り組んでいる途中で聞いたほうがよいです。
GitHubでは、チームの@exercism/learning-modeにメンションできます。Exercismフォーラムでは、Exercism Supportカテゴリーでイシューを立ててください。
経験から言えるのは、シラバスを育てる最も実践的な方法は、最も単純なコンセプトから始めて、コンセプトツリーを有機的に育てていくことだということです。すべてを前もって設計する必要はありませんし、実際のところ、あまり先のことまで考えないほうがうまくいくことが多いです。
まずは最小限のコンセプト、つまりその言語で何かを書くために最も基本的なものから始めます。また、一般的なエンジニアにとって最もなじみのあるコンセプトから始めるようにします。なじみがあるのはよいことです。なじみがあるものは混乱を招きません。
目指すゴールは慣用的なコードを書くことですが、そこへ至る途中の足がかりは、必ずしも慣用的ではありません。なじみのあるものを使うことは、たとえそれがその言語のよいコードの例でなくても、学習者がその言語らしいコードというゴールへより早く近づく助けになります。
コンセプトツリー全体を前もって描き出そうとするより、まずは最初の演習から始めましょう。最初の演習の目標は、学習者ができるだけ少ない抵抗で学び始められるようにすることです。学習者は、この言語のコードがどんな見た目なのかに慣れるための、まさに最初の一歩を踏み出します。少しだけコードを書くかもしれませんし、演習を終えるためにスタブに少し手を加えるだけかもしれません。この演習に取り組むために、学習者はすでに"Hello, World!"を解いています。ただし"Hello, World!"では、変えているのは文言だけです。言語の構文はまだほとんどなじみがないかもしれません。ここでは、すぐに達成感を得られることを優先し、先へ自信を持って進めるだけの構文の最低限になじんでもらうことを目指しましょう。
詳しくは、最初の演習の開発をお読みください。
最初の演習は、基本的なコンセプトを紹介するいくつかの演習をアンロックするべきです。プリミティブや基本的な型、そしてそれらの型に対する単純な操作などがこれにあたります。
詳しくは、次の演習の開発をお読みください。
ここから面白くなってくることもよくあります。この時点では、_紹介できる_ことが山ほどあります。次にどのコンセプトに取り組むかは、どうやって決めればよいのでしょうか?
実は、あまり気にしなくても大丈夫です。妥当だと思えるどこかから始めれば、それで問題ありません。
「妥当」をどう捉えているかについては、コンセプトツリーの拡張をご覧ください。
よいコンセプト演習は焦点が極めて絞られていて、理想的には1つのコンセプトだけを教えます。解き方も、通常は1つの想定されたアプローチしかありません。これに対し、プラクティス演習は終わりが決まっておらず、じっくり試行錯誤するのに向いています。
よいコンセプト演習は、たいていの場合、よいプラクティス演習にはなりませんし、その逆も同じです。プラクティス演習とコンセプト演習は目標がまったく異なるので、プラクティス演習をコンセプト演習に作り替えることはしません。コンセプト演習はすべて、一から書くか、単純なコンセプトを教えるために明確な意図をもって作られたストーリーを土台にします。
行き詰まりを感じることもあるでしょう。コンセプトAを理解するにはコンセプトBの理解が必要で、BにはAの理解が必要、という具合です。
そんなときは単純化しましょう。一方の複雑な部分はあえて曖昧にして、もう一方に学習者を慣れさせます。ある事柄は後でもっと詳しく紹介するとして、今はこの一点だけを理解すればよい、と言ってしまってまったく問題ありません。
コンセプトは、段階を踏んで、時間をかけて、より深く理解されていきます。
コンセプト演習には、必ずストーリーがあります。
他のトラックから演習をフォークする場合、その演習にはすでにストーリーがあります。その場合は、それで準備は完了です。
使えそうな既存のストーリーや、フォークできそうな演習があるかどうかは、ストーリーの一覧を見てみてください。
コンセプトはあるけれどストーリーがない場合は、紹介したいコンセプトを使った小さく単純なコード例を書くことをおすすめします。そして、そのコードに合うようにストーリーを逆算して考えます。ストーリーはとことん単純にしましょう。よいフィクションである必要はありません。しっかりした筋書きや人物の成長も要りません。ほんの数行でかまいません。
ストーリーのアイデアは、Exercismチームと気軽に話してみてください。ぴったりのストーリーを考える経験は豊富にあります。
ストーリーができたら、それに合うようにコードを少し調整する必要が出てくるでしょう。
シラバスの作成には、別々でありながら密接に絡み合う2つの活動があります。
より広いコミュニティに演習の実装に参加してもらうのは、楽しく、また実りが多いと感じています。一方で、シラバスの設計そのものは、複雑なところも含めてシラバス全体への理解を深めようとしている少人数のコントリビューターチームで取り組むほうが進めやすいです。
とはいえ、コミュニティからのコントリビューションを受け入れる前に、まずはシラバス設計チームが最初の5つか6つのコンセプトを実装することをおすすめします。こうすることで、シラバス設計の中核チームが、より広いコミュニティの人たちからのプルリクエストをレビューする前に、自分たちでそのプロセスを理解しておけます。
また、こうしたより高次のコンセプトのほうがイシューを立てやすく、気にする制約が少ないぶん、コミュニティのメンバーが取り組むのも楽しい傾向があります。
コンセプト演習を作るためのイシューの、最適な立て方はまだ見つかっていません。
いくつかのトラックでは、コンセプト自体と演習とでイシューを分けて作ってみました。別のトラックでは、チェックリストをこなしながら進めるイシューにしてみました。全体としては、まだハードルが高すぎると考えていて、もっとよい方法を見つけたいと思っています。
イシューを立て始めるタイミングで、このプロセスについてぜひ相談してください。どう進めればよいかを一緒に考えるために、できる限りのお手伝いをします。
よりよい進め方がわかったら、このドキュメントを更新していきます。