初心者必見！ChatGPTとOSSで爆速プログラミング学習！〜もうつまらない本もプログラミングスクールもいらない〜

# はじめに
はじめまして。都内のSaaS企業でバックエンドエンジニアをしているハセガワカンタです。今回はプログラミング言語のおすすめの学習方法を書いていきます。
プログラミング言語の学習は大変ですよね。何をどう学べばいいのか、どんな資料が役に立つのか、気軽に質問できるエンジニアが周りにいればいいですが全員がそうとは限りません。
しかし今は令和、そんな時の強い味方、ChatGPTの話をしようと思います。ChatGPTは大学のレポートを書いてくれるだけではなく、プログラミングを学ぶ上でめちゃくちゃ便利なんです。コードを投げれば、分かりやすい解説をくれるし、具体的な例も出してくれるので、理解が深まります。
この記事では、ChatGPTがどうやってプログラミングの学習を助けてくれるのか、その魅力と使い方をお伝えします。さあプログラミング初心者の方も、新しい言語を覚えたいベテランの方も、ChatGPT大先生を使って爆速で学習を進めましょう。

# プログラミング言語を学習することの難しさ
### 本やドキュメントを読んでも頭に入ってこない
プログラミングを学ぶとき、まず最初に本やドキュメントを読むでしょう。でも、理論だけを読んでいても、実際にコードを書く感覚はなかなか掴めません。例えば、クラスの基本的な概念は理解できても、それをどのように組み合わせて使うのか、実際のところは難しいんです。また学習用の本は多くの機能を網羅していてページ数が多いので、読むのに時間がかかりますし正直読み終わった段階で前半の内容は忘れていますw

### コードリーディングの題材がない
業務でプログラムを書いている人は、自分の仕事のコードを題材にできますが、そうでない方はどうでしょう？学んだことを実践するための具体的なコード例がないと、学習は理論的なままで終わってしまいます。どのように実世界でコードが使われているかを見ることは、学習をより深いものにするのに重要です。

### 適切な情報にアクセスできない
そして、最も大きな問題の一つが、適切なリソースにアクセスすることの難しさです。特定のプログラミング概念や文法について検索しようとしても、どのキーワードを使えばいいのか、どのリソースが役立つのかが分からないと、道は険しいです。初心者にとっては、何から手をつければいいのかさえ分からないことが多いです。例えば、エラーが発生したとき、ある程度経験のあるエンジニアなら、そのエラーメッセージや発生箇所から情報を整理して、何が原因で何を調べればいいのかを素早く理解できます。しかし、初心者や前提知識が足りない人にとっては、そもそもエラーの意味がわからず、エラーメッセージをそのままGoogle検索にかけることしかできないでしょう。その状態では本当に必要な情報にアクセスすることは難しいです。

# ChatGPTとOSSコードリーディングを活用した学習法
### OSSコードリーディングの重要性
実践的な学習には、オープンソースソフトウェア（OSS）のコードを読むことが欠かせません。OSSプロジェクトは、実際の開発環境で使われているコードの宝庫です。これを読むことでプログラミング言語の文法や概念がどのように実際のコードに適用されているかを直接見ることができます。また、OSSのコードは業務コードであまり見かけないような文法を使用していることが多く参考になります。理論を詰め込んでから実践するより、実践しながら理論を覚える方が身につきやすいと私は思っています。
もちろん規模の大きいプロジェクトは学習に向いていないので、複雑なことをしていない小さなプロジェクトで学習を行います。ChatGPTに「〇〇言語の学習のためにOSSのコードリーディングを行います。内容が複雑でなく、全部で500行くらいのプロジェクトを10個挙げてください。」とでも聞けば探してきてくれます。

### ChatGPTの活用法
OSSコードリーディングを行う際、ChatGPTは理解を助ける素晴らしいツールとなります。OSSで見つけた特定のコードスニペットや概念について疑問がある場合、その詳細がわかっていなくてもコードをそのまま貼り付ければChatGPTが問題を分割して教えてくれます。また文法単位ではなく、このクラスや関数がなんのために定義されているのか、なども教えてくれるため全体像の理解も深まります。適当に投げたコードからChatGPTが新たな文法や概念を教えてくれたらそれを題材とした簡単なサンプルプログラムも書かせることで、より一般的な使用方法が身につきます。

# 実例
実例として、筆者がRubyのライブラリ[ruby/time](https://github.com/ruby/time)を読みながら文法を勉強する流れをそのまま載せたいと思います。(文法の学習がメインなので読むファイルの順番とかはあまり気にしないでください)

質問
「これはruby/timeライブラリの一部です。このコードの文法を1行ずつ解説してください。」
```ruby
require "test/unit"
require "core_assertions"

Test::Unit::TestCase.include Test::Unit::CoreAssertions

module Test
  module Unit
    class TestCase
      def windows? platform = RUBY_PLATFORM
        /mswin|mingw/ =~ platform
      end
    end
  end
end
```

解答(※一部抜粋)

```ruby
require "test/unit"
```
> この行ではtest/unitライブラリを読み込んでいます。これはRubyの標準ライブラリの一部で、テストを書くための機能を提供します。

```ruby
require "core_assertions"
```
>core_assertionsを読み込んでいます。ただし、これは標準ライブラリや一般的なRubyライブラリの一部ではないため、カスタムライブラリか、特定の環境で提供されるものである可能性があります。

```ruby
Test::Unit::TestCase.include Test::Unit::CoreAssertions
```
>この行はTest::Unit::TestCaseクラスにTest::Unit::CoreAssertionsモジュールを組み込んでいます。これにより、TestCaseクラスのインスタンスがCoreAssertionsモジュールのメソッドを使用できるようになります。

こんな感じでよくわかっていなくても適当に投げるだけで解説してくれます。よくわからないところは追加で質問しましょう。

私「rubyでクラスにモジュールを組み込むと何が嬉しいのですか？またモジュールを組み込む方法を全て教えて。」

解答

>モジュールをクラスにインクルードすることの利点:
コードの再利用: 同じメソッドを複数のクラスで使用できます。
名前空間の整理: 関連するメソッドをモジュール内にグループ化することで、コードを整理しやすくなります。
メンテナンスの容易さ: モジュール内のメソッドを変更すると、そのモジュールをインクルードするすべてのクラスに変更が適用されます。
クラスにモジュールをインクルードする方法:
includeキーワード: これが最も一般的な方法です。includeを使用すると、モジュール内のメソッドがクラスのインスタンスメソッドとして追加されます。

```ruby
module MyModule
  def module_method
    "Hello from module!"
  end
end

class MyClass
  include MyModule
end

obj = MyClass.new
obj.module_method  # => "Hello from module!"
```
> extendキーワード: extendを使用すると、モジュール内のメソッドがクラスのクラスメソッド（静的メソッド）として追加されます。

```ruby
Copy code
class MyClass
  extend MyModule
end

MyClass.module_method  # => "Hello from module!"
```
> prependキーワード: Ruby 2.0以降で利用可能。prependを使用すると、モジュール内のメソッドがクラスの継承チェーンの先頭に挿入されます。これにより、モジュールのメソッドが同名のクラスのメソッドよりも優先されます。

```ruby
Copy code
class MyClass
  prepend MyModule
  def module_method
    "Hello from class!"
  end
end

obj = MyClass.new
obj.module_method  # => "Hello from module!" （モジュールが優先される）
```
> これらの方法を使用することで、Rubyプログラムの柔軟性と再利用性を高めることができます。

利用方法、簡単な例を挙げてくれましたね。`include`についてある程度は理解できたので、これ以上の細かい情報は公式ドキュメントなりを見ることにします。


次は以下の文法がよくわからないので投げてみることにします

```ruby
require "bundler/gem_tasks"
require "rake/testtask"

Rake::TestTask.new(:test) do |t|
  t.libs << "test/lib"
  t.ruby_opts << "-rhelper"
  t.test_files = FileList["test/**/test_*.rb"]
end

task :default => :test
```

解答(※一部抜粋)
```ruby
Rake::TestTask.new(:test) do |t|
```
> 新しいテストタスクを定義しています。このタスクは:testという名前で、ブロック内の設定に基づいて動作します。

解答読んでもよくわからないのでさらに聞いてみましょう

私「`Rake::TestTask.new(:test)`はクラスのインスタンス生成ですが、その後に続く `do |t| `はなんですか？」

解答

> Rake::TestTask.new(:test) do |t| の部分は、Rubyのブロックを用いた構文です。ここでは、Rake::TestTask クラスのインスタンスを生成しており、そのインスタンスに対してブロックを適用しています。
ブロック（do ... end または { ... } で囲まれた部分）は、Rubyで頻繁に使用される構文で、メソッドに渡すことができる一連の命令を定義します。ブロックは、メソッドの一部として実行され、メソッドから一時的なスコープとして使用される変数（この場合は t）を受け取ることができます。
この具体的なケースでは、Rake::TestTask.new(:test) によって新しい TestTask インスタンスが生成され、そのインスタンスがブロック内の変数 t に渡されます。ブロック内では、この t（TestTask インスタンス）に対してさまざまな設定を行います。
例えば、

```ruby
t.libs << "test/lib"
t.ruby_opts << "-rhelper"
t.test_files = FileList["test/**/test_*.rb"]
```
> これらの行は、TestTask インスタンス（t）の libs、ruby_opts、test_files といったプロパティに値を設定しています。
このようにブロックを使用することで、インスタンスの生成とそのインスタンスに対する設定を、簡潔かつ明確に一連のステップとして定義できます。

私
```ruby
t = Rake::TestTask.new(:test)
t.libs << "test/lib"
t.ruby_opts << "-rhelper"
t.test_files = FileList["test/**/test_*.rb"]
```

「ブロックを使用しない場合、これと同じ結果になりますか？」

解答(※一部抜粋)
> はい、ご提供いただいたコードは、以前のブロックを使用したコードと同じ機能を持っていますが、ブロックを使用せずに記述されています。具体的には以下のように動作します：

このように、どうやって検索したらよいかわからない文法も雑に投げるだけで必要な情報を手に入れることができるのです。

# 終わりに
この記事を通じて、ChatGPTとOSSコードリーディングを使った学習方法の有効性をご理解いただけたと思います。実際のコードを使って学ぶことで、理論だけでは得られない貴重な経験を積むことができます。ただしChatGPTは常に正しい回答を返すとは限らないので、最終的には公式ドキュメントや信頼性のある本などで回答のチェックをすることが重要です。ChatGPTとOSSコードを活用し、より楽しく、爆速で学習を進めていきましょう！