【生成AI】断捨離のススメ

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

## はじめに:eyeglasses:
この記事は技術書籍の断捨離とAI活用について記載しています

## 結論:eyeglasses:
もし断捨離に迷っているなら
AIと自分の判断を信じて有効な技術書籍だとしても勇気を持って捨てよう！


## 前置き:散らかった部屋と脳の関係:eyeglasses:
私達の脳には､｢ものの空間的位置｣を覚えておくための領域があると､Daniel J. Levitin は､著書「The Organized Mind」の中で指摘しています。追跡しなくてはならない情報が増えるほど､エネルギーを必要としてしまい､それだけ脳に負担がかかってしまいます｡
ボンド大学で､作業環境が認知やパフォーマンスに及ぼす影響について研究しているリビー・サンダー氏(ビジネス・スクール助教授)も、散らかった環境は人の認知や感情などにネガティブな影響を与える｡具体的には、集中力を低下させたり、ストレスや不安を高めたりすると指摘しています｡また､「人は無秩序な状態が目に入り続けると、それに認知資源（認知を働かせるためのエネルギー）を奪われてしまう」と､『Harvard Business Review』で解説しています｡

## 前置き:断捨離のメリット:eyeglasses:
**1. 脳のストレス軽減**
物が多い環境は、脳が無意識に情報を処理しようとするため、ストレスを引き起こします。
断捨離によって物を減らすことで、視覚的な刺激が少なくなり、心が落ち着きます。

**2. 集中力の向上**
余計な物がない環境では、注意を奪われる要素が減少します。
結果として、仕事や学習に集中しやすくなります。

**3. 時間と労力の節約**
物が少ないと整理整頓が簡単になり、探し物の時間が減ります。
また、掃除もしやすくなるため、家事の負担が軽減します。

**4. 自己管理能力の向上**
不要な物を手放す習慣がつくと、自分にとって本当に必要なものを見極める力が育ちます。
生活の優先順位をつけやすくなり、無駄な買い物も減ります。

**5. 精神的な解放感**
物への執着を手放すことで、心が軽くなり、ポジティブな気持ちになれます。
新しいことに挑戦する意欲が湧きやすくなるとも言われています。

**6. 経済的メリット**
不要な物を売ることで収入が得られる場合もあります。
さらに、今後の無駄な出費を減らす効果も期待できます。

断捨離は、物理的な空間を整えるだけでなく、心の整理にもつながります。シンプルな環境を作ることで、日常生活の質が向上しやすくなる点が大きな魅力です。


## 有用な技術書籍だとしても捨てるべきか
ここからが本題です
上記のメリットに従って私も断捨離を敢行してきました
子供の物が増えていき、家が広くないという理由が大きいですが、数年使ってないものは思い切って捨てました。

**しかし、有用な技術書籍は捨てることができませんでした**
**一度読んだけど、次の仕事で使うかも？　重要な知識だから復習したい・・・**
**知識力、技術力の商売だから、技術書籍も仕事道具の一部だし・・・**

などの理由で踏ん切りがつかなかったのですが
生成AIの登場により知識データベースは自分の脳みそではなく、WebやAIに外付け保存されていると考えた方が今の時代の最適解では？と考えるようになりました

ということで技術書籍についてAIに聞いて検証します

## リーダブルコード
<img width="100" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/249951/90f84a6b-1745-45c5-2f12-828891ef8982.jpeg">

https://www.oreilly.co.jp/books/9784873115658/

質問内容
```
リーダブルコードという技術書籍を知っていますか？
リーダブルコードの内容に沿って良いコードを提案してください
```

<details><summary>ChatGPT4 回答</summary>

『リーダブルコード』(Readable Code) は、コードを読みやすく、理解しやすくするためのベストプラクティスを紹介したプログラミング技術書です。執筆者は Dustin Boswell と Trevor Foucher で、特にプログラマーがコードを書く際に考慮すべきポイントを中心に述べています。以下はその主な内容と、それに基づく良いコード例です。

主な原則

    名前に意味を持たせる
    変数、関数、クラス名をわかりやすく具体的にする。

    コードを簡潔に、しかし明確にする
    短くすることを目的にせず、読みやすさを優先する。

    コメントを補助として使用する
    コードそのものが意図を伝えられるのが理想で、コメントは補足説明や背景情報のために使う。

    意図を明確にする
    コードが「何を」するかだけでなく、「なぜ」それをするのかを理解できるようにする。

    一貫性を保つ
    命名規則、フォーマット、関数の長さなどにおいて一貫性を守る。

良いコード例
問題：

以下のコードは読みにくいです。何をしているか一見してわかりません。


```py
def fn(arr):
    s = 0
    for x in arr:
        if x % 2 == 0:
            s += x
    return s
```
改善：

『リーダブルコード』の原則を適用して書き直します。
```py
def sum_even_numbers(numbers):
    """List内の偶数を合計する関数"""
    total = 0
    for number in numbers:
        if number % 2 == 0:
            total += number
    return total
```
改善ポイント:

    関数名 fn を sum_even_numbers に変更し、関数の目的を明確に。
    変数名 s を total に変更し、内容を具体的に。
    コメントを追加して関数の意図を説明。

コメントが必要な場合の例
```py
def calculate_discounted_price(price, discount_rate):
    """
    商品価格と割引率を元に割引後の価格を計算する。
    
    Parameters:
        price (float): 元の価格
        discount_rate (float): 割引率 (0.0 - 1.0)
    
    Returns:
        float: 割引後の価格
    """
    # 割引率が負または100%以上であればエラーを出す
    if not (0.0 <= discount_rate <= 1.0):
        raise ValueError("Discount rate must be between 0.0 and 1.0")
    return price * (1 - discount_rate)
```

改善ポイント:

    入力と出力を明確に説明するコメントをドキュメンテーションスタイルで記述。
    意図が不明な場合にエラーを発生させる防御的プログラミングを導入。

これらの例が『リーダブルコード』の原則に基づいた良いコードの参考になると思います！特定の場面での適用例や別の言語での例が必要であれば教えてください。

</details>

どうやらLLM(大規模言語モデル)の時点でリーダブルコードの知識はしっかり学習済みのようです
Gemini、perplexity、Claudeと別のAIに聞いてもしっかり回答できていました
ほぼ誤差ですが、今回はChatGPT4の回答が一番良い回答でした


## Java言語で学ぶデザインパターン入門
<img width="100" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/249951/b207e76c-bfc8-0d5d-81fb-91e914cf429d.jpeg">

https://www.amazon.co.jp/%E5%A2%97%E8%A3%9C%E6%94%B9%E8%A8%82%E7%89%88Java%E8%A8%80%E8%AA%9E%E3%81%A7%E5%AD%A6%E3%81%B6%E3%83%87%E3%82%B6%E3%82%A4%E3%83%B3%E3%83%91%E3%82%BF%E3%83%BC%E3%83%B3%E5%85%A5%E9%96%80-%E7%B5%90%E5%9F%8E-%E6%B5%A9/dp/4797327030/ref=tmm_other_meta_binding_swatch_0?_encoding=UTF8&qid=&sr=

質問内容
```
「Java言語で学ぶデザインパターン入門について」という技術書籍を知っていますか？
書籍の内容に沿ってそれぞれのデザインパターンと具体例を教えてください
```

<details><summary>ChatGPT4 回答</summary>
「Java言語で学ぶデザインパターン入門」は、結城浩さんが著した日本語の技術書で、デザインパターンをJavaで学ぶことに特化した内容です。この本は「GoF（Gang of Four）」のデザインパターンを元に、わかりやすく具体例を交えながら説明されています。

以下は書籍に基づく主なデザインパターンと、それぞれの具体例の概要です：

1. Iteratorパターン

    目的: コレクションの内部構造を隠しながら、要素を順にアクセスする仕組みを提供する。
    具体例: 書籍内では「本棚（Bookshelf）」を例に取り、Iteratorを使って本を順番に取り出す方法を解説しています。

2. Adapterパターン

    目的: 既存のクラスのインターフェースを他のインターフェースに適合させる。
    具体例: 「Banner」クラスを例にし、異なる表示方法（フレーム付きやアスタリスク付き）に変換するアダプタを作成します。

3. Template Methodパターン

    目的: 処理の枠組みを定義し、一部の具体的な実装をサブクラスに任せる。
    具体例: ゲームやドキュメントのフローの中で、サブクラスが独自の処理（例: 開始方法や終了方法）を提供する例を挙げています。

4. Factory Methodパターン

    目的: インスタンス生成の詳細を隠し、インスタンスの生成をサブクラスに委譲する。
    具体例: IDカード作成システムを例に取り、工場（Factory）でカードを作成する仕組みを紹介。

5. Singletonパターン

    目的: クラスのインスタンスを1つだけ生成し、それをどこからでもアクセス可能にする。
    具体例: データベース接続やログ管理クラスのように、アプリケーション全体で1つのインスタンスを共有するシナリオ。

6. Prototypeパターン

    目的: オブジェクトを複製して新しいインスタンスを生成する。
    具体例: 書籍内では文字列装飾など、プロトタイプを基に新しいオブジェクトを生成する方法を解説。

7. Builderパターン

    目的: 複雑なオブジェクトを段階的に構築する。
    具体例: HTMLドキュメントやテキスト文書の生成過程を例にし、段階的な構築方法を解説しています。

8. Compositeパターン

    目的: オブジェクトをツリー構造で管理し、個別オブジェクトとグループを同じ方法で操作できるようにする。
    具体例: ファイルとディレクトリの階層構造を例に、再帰的な操作を可能にする仕組みを紹介。

9. Strategyパターン

    目的: アルゴリズムの選択を動的に切り替えられるようにする。
    具体例: 書籍内ではジャンケンゲームを例に、異なる戦略（勝つ戦略、ランダム戦略など）を切り替えられる仕組みを解説。

10. Observerパターン

    目的: あるオブジェクトの状態が変化したときに、依存するオブジェクトに通知する。
    具体例: 温度センサーとディスプレイの関係を例に、リアルタイム更新を説明。

構造に関するパターン
Bridge パターン

    目的: 実装部分を抽象部分から分離し、独立して変更できるようにする。
    具体例: 文字列表示を例に、表示手段（例: 画面に表示、ファイルに保存）と表示内容を分けて実装。

Decorator パターン

    目的: オブジェクトに動的に新しい機能を追加する。
    具体例: テキスト編集ツールを例に、文字の装飾（太字、下線など）を動的に追加。

Facade パターン

    目的: サブシステムの複雑な操作を簡単なインターフェースで提供する。
    具体例: ホームオートメーションシステム（ライト、エアコン、カーテンなど）の一括操作。

Flyweight パターン

    目的: メモリ使用量を削減するため、共有可能なオブジェクトを再利用する。
    具体例: 図形描画ソフトで、同じ種類の図形（例: 線や円）のスタイル情報を共有。

Proxy パターン

    目的: 代理となるオブジェクトを使い、本物のオブジェクトへのアクセスを制御する。
    具体例: リモートの画像データを表示する際、画像のダウンロード完了前に「プロキシ」で仮の画像を表示。

</details>

GoFのデザインパターンも学習済みのようです
もう一つ質問してみましょう

```
Iteratorパターン を用いたソースコードのサンプルを書いてください
```

<details><summary>ChatGPT4 回答</summary>

以下は、Iteratorパターンを用いたJavaのサンプルコードです。この例では、**本棚（Bookshelf）**を表現し、その中の本を順番に取り出す仕組みを実装しています。

Iteratorパターンのサンプルコード
```java
import java.util.ArrayList;
import java.util.Iterator;
import java.util.List;

// 本クラス
class Book {
    private String name;

    public Book(String name) {
        this.name = name;
    }

    public String getName() {
        return name;
    }
}

// 本棚クラス (Iterableインターフェースを実装)
class BookShelf implements Iterable<Book> {
    private List<Book> books;

    public BookShelf() {
        this.books = new ArrayList<>();
    }

    // 本を追加するメソッド
    public void addBook(Book book) {
        books.add(book);
    }

    // 本の数を返すメソッド
    public int getSize() {
        return books.size();
    }

    // Iteratorを返す
    @Override
    public Iterator<Book> iterator() {
        return new BookShelfIterator(this);
    }

    // 本棚のリストを取得する
    protected List<Book> getBooks() {
        return books;
    }
}

// 本棚のIteratorクラス
class BookShelfIterator implements Iterator<Book> {
    private BookShelf bookShelf;
    private int index;

    public BookShelfIterator(BookShelf bookShelf) {
        this.bookShelf = bookShelf;
        this.index = 0;
    }

    // 次の本があるかどうかを確認
    @Override
    public boolean hasNext() {
        return index < bookShelf.getSize();
    }

    // 次の本を返す
    @Override
    public Book next() {
        return bookShelf.getBooks().get(index++);
    }
}

// メインクラス
public class IteratorPatternExample {
    public static void main(String[] args) {
        // 本棚を作成
        BookShelf bookShelf = new BookShelf();
        bookShelf.addBook(new Book("Design Patterns"));
        bookShelf.addBook(new Book("Effective Java"));
        bookShelf.addBook(new Book("Clean Code"));

        // Iteratorを使って本を順番に取り出す
        for (Book book : bookShelf) {
            System.out.println("Book: " + book.getName());
        }
    }
}
```

</details>

OK!
コードレベルでも問題ありませんね！

次は、少しだけマニアックな書籍について質問してみましょう

## UnityによるVRアプリケーション開発 ―作りながら学ぶバーチャルリアリティ入門
<img width="100" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/249951/6e1a5195-c09b-ea74-b830-11488c28ebfc.jpeg">

https://www.oreilly.co.jp/books/9784873117577/

質問内容
```
「UnityによるVRアプリケーション開発 ―作りながら学ぶバーチャルリアリティ入門」という技術書籍を知っていますか？
書籍の内容に沿ってVRアプリケーション開発の重要ポイントを５つ挙げてください
また、ソースコードによる実例もお願いします
```


<details><summary>ChatGPT4 回答</summary>
「UnityによるVRアプリケーション開発 ―作りながら学ぶバーチャルリアリティ入門」は、Unityを使ったVRアプリケーションの開発方法を学ぶための日本語技術書です。内容は、VRの基本概念から、Unityを活用した具体的な開発手法まで幅広く扱っています。

以下に、この書籍の内容に基づいたVRアプリケーション開発の重要ポイントと、簡単なソースコードの実例を示します。

VRアプリケーション開発の重要ポイント

    VRデバイスの設定とUnity環境構築
        UnityにVRサポートを有効化し、OculusやHTC Viveなどのデバイスをセットアップ。
        ポイント: UnityのXR Plugin Managementを活用してプラットフォームごとのデバイス設定を簡略化。

    インタラクション設計
        ユーザーがVR空間でオブジェクトとどのように対話するか（例: グラブ、クリック）。
        ポイント: 手やコントローラーの動きをトラッキングし、自然な操作感を提供。

    空間オーディオの利用
        音声を立体的に再生して、リアルな体験を実現。
        ポイント: UnityのAudioSourceとSpatial Audio設定を使用。

    パフォーマンスの最適化
        VRは高フレームレート（通常90FPS以上）が求められるため、最適化が不可欠。
        ポイント: オブジェクトのポリゴン数やリアルタイムライトを減らし、GPU負荷を軽減。

    没入感のデザイン
        ユーザーが没入感を感じるために、直感的なUIや物理エンジンを駆使する。
        ポイント: ユーザーの視点を中心にデザインし、3Dオブジェクトのスケール感を適切に調整。


ソースコードによる実例
例: VR空間内でオブジェクトを掴む

以下は、UnityでVRハンドコントローラーを使って、オブジェクトを掴む処理の実例です。
```C#
using UnityEngine;

public class GrabObject : MonoBehaviour
{
    private GameObject grabbedObject = null;
    private Transform originalParent;
    public Transform handTransform; // コントローラーまたは手のTransform

    void Update()
    {
        if (Input.GetButtonDown("Fire1")) // グリップボタンの入力
        {
            TryGrab();
        }
        else if (Input.GetButtonUp("Fire1")) // ボタンを離したとき
        {
            Release();
        }
    }

    private void TryGrab()
    {
        Ray ray = new Ray(handTransform.position, handTransform.forward); // 手の向きにレイを発射
        if (Physics.Raycast(ray, out RaycastHit hit, 2.0f)) // 2メートル以内のオブジェクトを探す
        {
            if (hit.collider.CompareTag("Grabbable")) // "Grabbable"タグが付いたオブジェクトのみ掴む
            {
                grabbedObject = hit.collider.gameObject;
                originalParent = grabbedObject.transform.parent;
                grabbedObject.transform.SetParent(handTransform); // 手の子オブジェクトに設定
                grabbedObject.GetComponent<Rigidbody>().isKinematic = true; // 物理挙動を無効化
            }
        }
    }

    private void Release()
    {
        if (grabbedObject != null)
        {
            grabbedObject.GetComponent<Rigidbody>().isKinematic = false; // 物理挙動を有効化
            grabbedObject.transform.SetParent(originalParent); // 元の親に戻す
            grabbedObject = null;
        }
    }
}
```

コード解説

    Raycastで対象オブジェクトを取得:
        ハンドコントローラーの位置と向きを基準にレイを飛ばし、対象物を検出します。

    オブジェクトのタグをチェック:
        「Grabbable」タグが付いたオブジェクトのみ掴むようにしています。

    掴む処理 (SetParent):
        掴んだオブジェクトを手の子オブジェクトに設定し、親子関係を変更します。

    リリース処理:
        オブジェクトを元の親に戻し、物理挙動を再び有効化します。


このサンプルを使えば、基本的なVR空間での「物を掴む」動作を再現できます。本書では、これらの基本動作に加え、UIや空間デザインの詳細なポイントも紹介されていますので、さらなる学習に役立ててください！
</details>


書籍の内容に沿って回答できていますね
古い書籍は大体学習済みのように思えます

## まとめ
当初は技術書籍をPDF化して、読み込ませるなども考えてましたが
回答精度が高いのでその必要もないと感じました

忙しい身分としてはPDF化する手間も省きかったので今回の検証結果に満足しています
これでさらに断捨離が捗ります！

もし100%の回答精度を求めている方は
[GPTs](https://qiita.com/kerimeka/items/5cf23dd20b1339675245) や [NotebookLM](https://notebooklm.google.com/?original_referer=https:%2F%2Fwww.google.com%23&pli=1)でも手軽にRAG作成ができるので、こちらもご検討ください！

次は、[@nissy_gp](https://qiita.com/nissy_gp)さんの記事です。
お楽しみに！！