演習 - GitHub Copilot ツールを使用してコード機能を開発する

完了

あなたと同僚は、図書館アプリケーションの目標について話し合うためにミーティングを行います。 あなたは、図書館司書と利用者のユーザー エクスペリエンスを向上させたいと考えています。 アプリケーションに追加できるいくつかの新機能について説明します。

あなたは、次の機能に取り組むことに同意します。

  • 書籍の在庫:図書館司書が書籍の在庫の状態を判断できるようにします。 この機能では、書籍が貸出可能かどうか、または現在ほかの利用者に貸出中の場合は返却期限を示すメッセージを表示する必要があります。

  • 書籍の貸出:図書館司書が書籍を利用者に貸し出せるようにします (書籍が利用可能な場合)。 この機能は、利用者が貸出中の本を受け取るオプションを表示し、Loans.json を新しい貸出内容で更新して、利用者の更新された貸出の詳細を表示する必要があります。

  • 書籍の予約:図書館司書が利用者のために書籍を予約できるようにします (書籍が既に予約されている場合を除く)。 この機能は、新しい書籍予約プロセスを実装する必要があります。 この機能では、予約プロセスのサポートに必要な新しいクラスとインターフェイスと共に、新しい Reservations.json ファイルを作成する必要がある場合があります。

各メンバーが、新しい機能のうち 1 つに取り組んでから、再グループ化します。 あなたは、書籍の在庫の状態を判断する機能に取り組みます。 同僚は、書籍を利用者に貸し出す機能に取り組みます。 最後の、利用者のために書籍を予約する機能は、他の 2 つの機能が完了した後に開発されます。

この演習では、次のタスクを実行します。

  1. コード リポジトリに "書籍の在庫" ブランチを作成します。

  2. 新しい "書籍の在庫" 機能を開発します。

    • GitHub Copilot の提案を使用して、コードをより迅速かつ正確に実装できるようにします。
    • コードの更新をリモート リポジトリの "書籍の在庫" ブランチと同期させます。
  3. 変更をリポジトリのメイン ブランチにマージする pull request を作成します。

リポジトリに新しいブランチを作成する

新しい "書籍の在庫" 機能の開発を開始する前に、リポジトリに新しいブランチを作成する必要があります。 これにより、リポジトリのメイン ブランチに影響を与えずに、新しい機能に取り組むことができます。 新しい機能の準備ができたら、メイン ブランチにマージできます。

以下の手順に従って、演習のこのセクションを完了します。

  1. Visual Studio Code に AccelerateDevGitHubCopilot ソリューションが開かれていることを確認します。

  2. [ソース管理] ビューを選択し、ローカル リポジトリがリモート リポジトリ (プルまたは同期) と同期していることを確認します。

  3. ウィンドウの左下隅にある [メイン] を選択します。

  4. 新しいブランチを作成するには、「書籍の在庫」と入力したあと、[+ 新しいブランチの作成] を選択します。

  5. 新しいブランチをリモート リポジトリにプッシュするには、[ブランチの発行] を選択します。

図書館司書が書籍の在庫の状態を判断できるようにする機能を開発する

演習のこのセクションでは、GitHub Copilot を使用して、図書館アプリケーションの新機能の実装に役立てます。 新しい機能を使用すると、図書館司書は書籍の在庫の状態を判断できるようになります。

書籍の在庫の機能には、次のコード更新プログラムが含まれている必要があります。

  • 新しい SearchBooks アクションを CommonActions に追加します。
  • ConsoleApp.csで WriteInputOptions メソッドを更新します。 新しい CommonActions.SearchBooks オプションのサポートを追加します。 書籍が貸出可能かどうかを確認するオプションを表示します。
  • ConsoleApp.csで ReadInputOptions メソッドを更新します。 新しい CommonActions.SearchBooks オプションのサポートを追加します。
  • ConsoleApp.csで PatronDetails メソッドを更新します。 CommonActions.SearchBooks を呼び出す前に、optionsReadInputOptions を追加します。 else if アクションを処理する SearchBooks を追加します。 else if ブロックは、SearchBooks という名前の新しいメソッドを呼び出す必要があります。
  • ConsoleApp.cs に新しい SearchBooks メソッドを作成します。 SearchBooks メソッドは、ユーザーが指定した書籍のタイトルを読み取る必要があります。 書籍が貸出可能かどうかを確認し、"book.title は貸出可能です" または "book.title は、別の利用者に貸し出されています" のうちいずれかのメッセージを表示します。 返却期限は loan.DueDate です。

以下の手順に従って、演習のこのセクションを完了します。

  1. [ソリューション エクスプローラー] ビューを開きます。

  2. CommonActions.cs ファイルを開き、CommonActions 列挙型を選択します。

    SearchBooks に新しい CommonActions アクションを追加する必要があります。

  3. インライン チャットを開き、次のプロンプトを入力します。

    Update selection to include a new `SearchBooks` action.
    

    GitHub Copilot により、新しい SearchBooks アクションを CommonActions 列挙型に追加するコードの更新が提案されます。

  4. 推奨された更新を確認し、[承諾] を選択します。

    public enum CommonActions
    {
        Repeat = 0,
        Select = 1,
        Quit = 2,
        SearchPatrons = 4,
        RenewPatronMembership = 8,
        ReturnLoanedBook = 16,
        ExtendLoanedBook = 32,
        SearchBooks = 64
    }
    
  5. ConsoleApp.cs ファイルを開きます。

  6. WriteInputOptions メソッドを見つけて選択します。

    新しい CommonActions.SearchBooks オプションのサポートを追加する必要があります。 書籍が貸出可能かどうかを確認するオプションを表示します。

  7. インライン チャットを開き、次のプロンプトを入力します。

    Update selection to include an option for the `CommonActions.SearchBooks` action. Use the letter "b" and the message "to check for book availability".
    

    GitHub Copilot により、if アクションの新しい SearchBooks ブロックを追加するコードの更新が提案されます。

  8. 推奨された更新を確認し、[承諾] を選択します。

    提案される更新は、次のコード スニペットのような内容になります。

    static void WriteInputOptions(CommonActions options)
    {
        Console.WriteLine("Input Options:");
        if (options.HasFlag(CommonActions.ReturnLoanedBook))
        {
            Console.WriteLine(" - \"r\" to mark as returned");
        }
        if (options.HasFlag(CommonActions.ExtendLoanedBook))
        {
            Console.WriteLine(" - \"e\" to extend the book loan");
        }
        if (options.HasFlag(CommonActions.RenewPatronMembership))
        {
            Console.WriteLine(" - \"m\" to extend patron's membership");
        }
        if (options.HasFlag(CommonActions.SearchPatrons))
        {
            Console.WriteLine(" - \"s\" for new search");
        }
        if (options.HasFlag(CommonActions.SearchBooks))
        {
            Console.WriteLine(" - \"b\" to check for book availability");
        }
        if (options.HasFlag(CommonActions.Quit))
        {
            Console.WriteLine(" - \"q\" to quit");
        }
        if (options.HasFlag(CommonActions.Select))
        {
            Console.WriteLine("Or type a number to select a list item.");
        }
    }
    
  9. 少し上スクロールして、ReadInputOptions メソッドを見つけて選択します。

    新しい CommonActions.SearchBooks オプションのサポートを追加する必要があります。 ユーザーが SearchBooks アクションを選択する場合の処理を含めます。

  10. インライン チャットを開き、次のプロンプトを入力します。

    Update selection to include an option for the `CommonActions.SearchBooks` action.
    

    GitHub Copilot により、case アクションを選択するユーザーを処理する新しい SearchBooks を追加するコードの更新が提案されます。

  11. 推奨された更新を確認し、[承諾] を選択します。

    提案される更新は、次のコード スニペットのような内容になります。

    static CommonActions ReadInputOptions(CommonActions options, out int optionNumber)
    {
        CommonActions action;
        optionNumber = 0;
        do
        {
            Console.WriteLine();
            WriteInputOptions(options);
            string? userInput = Console.ReadLine();
    
            action = userInput switch
            {
                "q" when options.HasFlag(CommonActions.Quit) => CommonActions.Quit,
                "s" when options.HasFlag(CommonActions.SearchPatrons) => CommonActions.SearchPatrons,
                "m" when options.HasFlag(CommonActions.RenewPatronMembership) => CommonActions.RenewPatronMembership,
                "e" when options.HasFlag(CommonActions.ExtendLoanedBook) => CommonActions.ExtendLoanedBook,
                "r" when options.HasFlag(CommonActions.ReturnLoanedBook) => CommonActions.ReturnLoanedBook,
                "b" when options.HasFlag(CommonActions.SearchBooks) => CommonActions.SearchBooks,
                _ when int.TryParse(userInput, out optionNumber) => CommonActions.Select,
                _ => CommonActions.Repeat
            };
    
            if (action == CommonActions.Repeat)
            {
                Console.WriteLine("Invalid input. Please try again.");
            }
        } while (action == CommonActions.Repeat);
        return action;
    }
    
  12. 下スクロールして、PatronDetails メソッドを検索して選択します。

    2 つのことを実行する必要があります。

    • CommonActions.SearchBooks を呼び出す前に、optionsReadInputOptions を追加する必要があります。
    • また、else if アクションを処理する SearchBooks を追加する必要もあります。 else if ブロックは、SearchBooks という名前の新しいメソッドを呼び出す必要があります。

    これらの両方に一緒に対処できます。

  13. インライン チャットを開き、次のプロンプトを入力します。

    Update selection to add `CommonActions.SearchBooks` to `options` before calling `ReadInputOptions`. Add an `else if` block to handle the `SearchBooks` action. The `else if` block should call a new method named `SearchBooks`.
    

    GitHub Copilot により、CommonActions.SearchBooks を呼び出す前に optionsReadInputOptions を追加するコード更新が提案されます。

  14. 推奨された更新を確認し、[承諾] を選択します。

    async Task<ConsoleState> PatronDetails()
    {
        Console.WriteLine($"Name: {selectedPatronDetails.Name}");
        Console.WriteLine($"Membership Expiration: {selectedPatronDetails.MembershipEnd}");
        Console.WriteLine();
        Console.WriteLine("Book Loans:");
        int loanNumber = 1;
        foreach (Loan loan in selectedPatronDetails.Loans)
        {
            Console.WriteLine($"{loanNumber}) {loan.BookItem!.Book!.Title} - Due: {loan.DueDate} - Returned: {(loan.ReturnDate != null).ToString()}");
            loanNumber++;
        }
    
        CommonActions options = CommonActions.SearchPatrons | CommonActions.Quit | CommonActions.Select | CommonActions.RenewPatronMembership | CommonActions.SearchBooks;
        CommonActions action = ReadInputOptions(options, out int selectedLoanNumber);
        if (action == CommonActions.Select)
        {
            if (selectedLoanNumber >= 1 && selectedLoanNumber <= selectedPatronDetails.Loans.Count())
            {
                var selectedLoan = selectedPatronDetails.Loans.ElementAt(selectedLoanNumber - 1);
                selectedLoanDetails = selectedPatronDetails.Loans.Where(l => l.Id == selectedLoan.Id).Single();
                return ConsoleState.LoanDetails;
            }
            else
            {
                Console.WriteLine("Invalid book loan number. Please try again.");
                return ConsoleState.PatronDetails;
            }
        }
        else if (action == CommonActions.Quit)
        {
            return ConsoleState.Quit;
        }
        else if (action == CommonActions.SearchPatrons)
        {
            return ConsoleState.PatronSearch;
        }
        else if (action == CommonActions.RenewPatronMembership)
        {
            var status = await _patronService.RenewMembership(selectedPatronDetails.Id);
            Console.WriteLine(EnumHelper.GetDescription(status));
            // reloading after renewing membership
            selectedPatronDetails = (await _patronRepository.GetPatron(selectedPatronDetails.Id))!;
            return ConsoleState.PatronDetails;
        }
        else if (action == CommonActions.SearchBooks)
        {
            return await SearchBooks();
        }
    
        throw new InvalidOperationException("An input option is not handled.");
    }
    

    インライン チャットの提案により、SearchBooks メソッドのスタブ コードが作成される場合もあります。

  15. 少し時間をかけて SearchBooks メソッドのプロセス要件を検討してみましょう。

    メソッドは何を行う必要がありますか? 何を返す必要がありますか? パラメーターは必要ですか?

    SearchBooks メソッドは、次のプロセスを実装する必要があります。

    1. ユーザーに書籍のタイトルの入力を求めるメッセージを表示する。

    2. ユーザーが指定した書籍のタイトルを読み取る。

    3. 書籍が貸出可能かどうかを確認する

    4. 次のいずれかのオプションを示すメッセージを表示する。

      • "book.title は貸出可能です"
      • book.title は別の利用者に貸し出されています。 返却期限は loan.DueDate です。

    メッセージ オプションをビルドするには、コードで次の JSON ファイルにアクセスする必要があります。

    • Books.json は、一致する TitleBookId を見つけるために必要です。
    • Loans.json は、一致する ReturnDateDueDateBookItemId を見つけるために必要です。 BookItemId は、BookIdBooks.json と同じです。
  16. ConsoleApp.cs ファイルに次の SearchBooks メソッドが作成されていることを確認します。

    async Task<ConsoleState> SearchBooks()
    {
    
        return ConsoleState.PatronDetails;
    }
    

    GitHub Copilot によって作成されたコード コメントは必ず削除してください。 不要で不正確なコメントは、GitHub Copilot の提案に悪影響を及ぼすおそれがあります。

  17. SearchBooks メソッドを選択します。

  18. インライン チャットを開き、次のプロンプトを入力します。

    Update selection to obtain a book title. Prompt the user to "Enter a book title to search for". Read the user input and ensure the book title isn't null.
    

    GitHub Copilot により、ユーザーが指定した書籍のタイトルをキャプチャするコード更新プログラムが提案されます。

  19. 推奨された更新を確認し、[承諾] を選択します。

    async Task<ConsoleState> SearchBooks()
    {
        string? bookTitle = null;
        while (String.IsNullOrWhiteSpace(bookTitle))
        {
            Console.Write("Enter a book title to search for: ");
            bookTitle = Console.ReadLine();
        }
    
        // Perform book search logic here
    
        return ConsoleState.PatronDetails;
    }
    
  20. SearchBooks メソッドを選択します。

    GitHub Copilot では、書籍タイトルのユーザー入力を処理する別のメソッドを作成できます。 SearchBooks メソッドのプライマリ ロジックを引き続き開発できます。

  21. チャット ビューを開きます。

  22. チャット コンテキストに次のファイルを追加します: ConsoleApp.cs、JsonData.cs、JsonLoanRepository.cs、Books.json、Loans.json、BookItems.json。

  23. 次のプロンプトを入力します。

    @workspace  Explain how to update the `SearchBooks` method and ConsoleApps class to find a matching book title in the `Books.json` file. Use the user supplied book title to find a matching book. If a book is found, use Loans.json to check if the book is available for loan. If the book has been returned, display a message stating "`book.title` is available for loan". If the book is on loan, display a message stating "`book.title` is on loan to another patron. The return due date is `loan.DueDate`".
    
  24. 少し時間をかけて、提案された更新を確認しましょう。

    GitHub Copilot は、次のような候補に類似した更新プログラムを提案する必要があります。

    SearchBooks ファイル内でタイトルが一致する書籍を検索し、その書籍が貸し出し可能かどうかを確認できるように ConsoleApp メソッドと Books.json クラスを更新するには、次の手順に従います。

    a. 書籍をタイトルで検索するメソッドを JsonData クラスに追加します。 b。 この新しいメソッドを使用するように SearchBooks クラス内の ConsoleApp メソッドを更新します。 c. 書籍の貸出状態を確認し、適切なメッセージを表示します。

    更新されたコードを次に示します。

    手順 1: JsonData クラスでタイトル別に書籍を検索するメソッドを追加する

    public class JsonData
    {
        // Existing code...
    
        public Book? SearchBookByTitle(string title)
        {
            return Books?.FirstOrDefault(b => b.Title.Equals(title, StringComparison.OrdinalIgnoreCase));
        }
    }
    

    手順 2: ConsoleApp クラスの SearchBooks メソッドを更新する

    public class ConsoleApp
    {
        // Existing fields...
    
        JsonData _jsonData;
    
        public ConsoleApp(ILoanService loanService, IPatronService patronService, IPatronRepository patronRepository, ILoanRepository loanRepository, JsonData jsonData)
        {
            _patronRepository = patronRepository;
            _loanRepository = loanRepository;
            _loanService = loanService;
            _patronService = patronService;
            _jsonData = jsonData;
        }
    
        // Existing methods...
    
        async Task<ConsoleState> SearchBooks()
        {
            string bookTitle = ReadBookTitle();
    
            Book? book = _jsonData.SearchBookByTitle(bookTitle);
    
            if (book == null)
            {
                Console.WriteLine($"No book found with title: {bookTitle}");
                return ConsoleState.PatronDetails;
            }
    
            Loan? loan = _jsonData.Loans?.FirstOrDefault(l => l.BookItemId == book.Id && l.ReturnDate == null);
    
            if (loan == null)
            {
                Console.WriteLine($"{book.Title} is available for loan.");
            }
            else
            {
                Console.WriteLine($"{book.Title} is on loan to another patron. The return due date is {loan.DueDate}.");
            }
    
            return ConsoleState.PatronDetails;
        }
    
        // Existing methods...
    }
    

    手順 3:JsonData を ConsoleApp に渡すように Program.cs を更新する

    using Microsoft.Extensions.DependencyInjection;
    using Library.Infrastructure.Data;
    using Library.ApplicationCore;
    using Microsoft.Extensions.Configuration;
    
    var services = new ServiceCollection();
    
    var configuration = new ConfigurationBuilder()
    .SetBasePath(Directory.GetCurrentDirectory())
    .AddJsonFile("appSettings.json")
    .Build();
    
    services.AddSingleton<IConfiguration>(configuration);
    
    services.AddScoped<IPatronRepository, JsonPatronRepository>();
    services.AddScoped<ILoanRepository, JsonLoanRepository>();
    services.AddScoped<ILoanService, LoanService>();
    services.AddScoped<IPatronService, PatronService>();
    
    services.AddSingleton<JsonData>();
    services.AddSingleton<ConsoleApp>();
    
    var servicesProvider = services.BuildServiceProvider();
    
    var consoleApp = servicesProvider.GetRequiredService<ConsoleApp>();
    consoleApp.Run().Wait();
    

    これらの変更により、SearchBooks クラス内の ConsoleApp メソッドは、Books.json ファイル内のタイトルで書籍を検索し、Loans.json ファイルでその貸し出し状態を確認します。 書籍が貸出可能な場合は、書籍が貸出可能であることを示すメッセージが表示されます。 書籍が貸出中の場合は、書籍が貸出中であることを示すメッセージが表示され、返却期限が表示されます。

  25. 提案されたメソッドを JsonData クラスの末尾に追加します。

    public Book? SearchBookByTitle(string title)
    {
        return Books?.FirstOrDefault(b => b.Title.Equals(title, StringComparison.OrdinalIgnoreCase));
    }
    
  26. 提案された更新を使用して Program.cs ファイルを更新します。

    using Microsoft.Extensions.DependencyInjection;
    using Library.Infrastructure.Data;
    using Library.ApplicationCore;
    using Microsoft.Extensions.Configuration;
    
    var services = new ServiceCollection();
    
    var configuration = new ConfigurationBuilder()
    .SetBasePath(Directory.GetCurrentDirectory())
    .AddJsonFile("appSettings.json")
    .Build();
    
    services.AddSingleton<IConfiguration>(configuration);
    
    services.AddScoped<IPatronRepository, JsonPatronRepository>();
    services.AddScoped<ILoanRepository, JsonLoanRepository>();
    services.AddScoped<ILoanService, LoanService>();
    services.AddScoped<IPatronService, PatronService>();
    
    services.AddSingleton<JsonData>();
    services.AddSingleton<ConsoleApp>();
    
    var servicesProvider = services.BuildServiceProvider();
    
    var consoleApp = servicesProvider.GetRequiredService<ConsoleApp>();
    consoleApp.Run().Wait();
    
  27. JsonData _jsonData; フィールド宣言を ConsoleApp クラスのクラス コンストラクターの前に追加します。

  28. JsonData jsonData パラメーターを ConsoleApp クラス コンストラクターに追加し、それを使用してコンストラクター内の _jsonData フィールドを初期化します。

    更新されたクラス コンストラクターは、次のコード スニペットのようになります。

    public ConsoleApp(ILoanService loanService, IPatronService patronService, IPatronRepository patronRepository, ILoanRepository loanRepository, JsonData jsonData)
    {
        _patronRepository = patronRepository;
        _loanRepository = loanRepository;
        _loanService = loanService;
        _patronService = patronService;
        _jsonData = jsonData;
    }
    
  29. JsonData は ConsoleApp クラスで認識されていないことに注意してください。

    using Library.Infrastructure.Data; ファイルの先頭に ConsoleApp.cs を追加する必要があります。

  30. using Library.Infrastructure.Data; ステートメントは、必ず ConsoleApp.cs ファイルの先頭に追加します。

  31. コード候補を使用して、SearchBooks メソッドを更新します。

    提案されたコードは、LINQ クエリを使用してタイトルで書籍を検索します。 書籍が見つかった場合は、別の LINQ クエリを使用して、書籍が貸出中かどうかを判断します。 このコードには、検索結果に基づいて書籍の在庫状態を表示するロジックも含まれています。 応答メッセージの表示に使用されるロジックを実装する方法がいくつかあります。 例は以下のコード スニペットに示されています。

    次のコード スニペットに、SearchBooks メソッドの 1 つの可能な実装を示します。

    async Task<ConsoleState> SearchBooks()
    {
        string bookTitle = ReadBookTitle();
    
        Book? book = _jsonData.SearchBookByTitle(bookTitle);
    
        if (book == null)
        {
            Console.WriteLine($"No book found with title: {bookTitle}");
            return ConsoleState.PatronDetails;
        }
    
        Loan? loan = _jsonData.Loans?.FirstOrDefault(l => l.BookItemId == book.Id && l.ReturnDate == null);
    
        if (loan == null)
        {
            Console.WriteLine($"{book.Title} is available for loan.");
        }
        else
        {
            Console.WriteLine($"{book.Title} is on loan to another patron. The return due date is {loan.DueDate}.");
        }
    
        return ConsoleState.PatronDetails;
    }
    
  32. SearchBooks メソッドを選択します。

  33. チャット ビューを開き、次のプロンプトを入力します。

    Explain the LINQ queries and the evaluation of the book's availability status.
    
  34. 少し時間をかけて、GitHub Copilot から提供された説明を確認しましょう。

    書籍が貸出中かどうかを確認するクエリには、次の説明に似た内容が表示されるはずです。

    **Search for the Loan Status of the Book**
    
    Loan? loan = _jsonData.Loans?.FirstOrDefault(l => l.BookItemId == book.Id && l.ReturnDate == null);
    
    - _jsonData.Loans: Accesses the list of loans from the JsonData class.
    
    - ?.: The null-conditional operator ensures that if _jsonData.Loans is null, the entire expression will return null without throwing a NullReferenceException.
    
    - FirstOrDefault: A LINQ method that returns the first element in the collection that matches the specified condition, or null if no such element is found.
    
    - Lambda Expression: l => l.BookItemId == book.Id && l.ReturnDate == null
    
        - l.BookItemId == book.Id: Checks if the BookItemId of the loan matches the Id of the book being searched.
    
        - l.ReturnDate == null: Checks if the loan's ReturnDate is null, indicating that the book is currently on loan and has not been returned.
    
    - Result: If a matching loan is found, it is assigned to the loan variable. If no matching loan is found, loan is null.
    
    **Evaluation of the Book's Availability Status**
    
    After executing the LINQ queries, the method evaluates the availability status of the book:
    
      - If `loan` is `null`, the book has been returned. The method prints that the book is available for loan.
      - If `loan` is not `null`, the book is currently on loan (no return date). The method prints that the book is on loan and provides the date when the book should be returned.
    
    
  35. Check if the Book is on Loan (書籍が貸出中かどうかを確認する) クエリによって実装されたロジックを検証します。

    null 条件演算子:?. 演算子は null 条件演算子です。 これにより、_jsonData.Loansnull の場合、式全体が null をスローせずに NullReferenceException と評価されるようになります。

    ラムダ式:ラムダ式 l => l.BookItemId == book.Id && l.ReturnDate == null は、FirstOrDefault メソッドの条件を定義します。 各 loan オブジェクト l をチェックして、その BookItemIdId オブジェクトの book と一致するかどうか、およびその ReturnDatenull かどうかを確認します。

    このコードは、loan が指定された _jsonData.LoansBookItemId と一致し Idbook である、ReturnDate コレクション内の最初の nullを検索しようとします。 そのような loan が見つからない場合、または _jsonData.Loansnull の場合、loannull に設定されます。

    ほとんどの現代の図書館には、同じ書籍が複数冊所蔵されています。 このコードは、各書籍が 1 冊だけであることを前提としています。 図書館に同じ書籍が複数ある場合は、同じ書籍の複数の貸出を処理するためにコードを更新する必要があります。 このトレーニングの目的上、各書籍は 1 冊だけであり、提供されるロジックで十分であると想定しています。

  36. エラーが発生しないようにソリューションをビルドします。

    警告メッセージが表示されますが、エラーは発生しません。

    ソリューション エクスプローラー ビューでソリューションをビルドするには、AccelerateDevGitHubCopilot を右クリックし、[ビルド] を選択します。

変更をリモート リポジトリと同期する

  1. [ソース管理] ビューを選択します。

  2. 更新したファイルが [変更] の一覧に表示されていることを確認します。

  3. GitHub Copilot を使用して、[コミット] のメッセージを生成します。

  4. 変更をステージングしてコミットするには、[コミット] を選択してから、[はい] を選択します。

  5. 変更をリモート リポジトリに同期 (またはプッシュ) します。

作業を確認

演習のこのセクションでは、次のタスクを完了します。

  1. 新しい機能で、書籍の在庫の状態が正しく決定されることを確認します。
  2. 変更をリポジトリのメイン ブランチにマージする pull request を作成します。

新しい機能が期待どおりに動作することを確認する

自動テストがないため、手動テストを使用して、新しい機能が期待どおりに動作することを確認できます。 検証できるデータ ソースを使用することが重要です。 この場合は、Books.jsonLoans.json ファイルを使用して、新しい機能が書籍の在庫状態を正しく報告することを確認します。

以下の手順に従って、演習のこのセクションを完了します。

  1. [ソリューション エクスプローラー] ビューを開きます。

  2. アプリケーションを実行するには、Library.Console を右クリックし、[デバッグ] を選択してから [新しいインスタンスを開始] を選択します。

  3. 利用者名の入力を求められたら、「One」と入力して Enter キーを押します。

    検索クエリに一致する利用者の一覧が表示されます。

  4. "Input Options" プロンプトで「2」と入力し、Enter キーを押します。

    2」と入力すると、リストにある 2 番目のパトロンが選択されます。

    利用者の名前とメンバーシップの状態が表示され、その後に書籍貸出の詳細が表示されます。

  5. "Input Options" プロンプトで「b」と入力し、Enter キーを押します。

    b」と入力すると、書籍の在庫状態を検索するオプションが選択されます。

    書籍のタイトルを入力するプロンプトが表示されます。

  6. Book One」と入力し Enter キーを押します。

    ダウンロードした元のデータでは、Book One は現在 Patron Forty-Nineに貸出中であるため、在庫がありません。

  7. 書籍が別の利用者に貸し出されていることを示すメッセージがアプリケーションに表示されることを確認します。

  8. Book NinePatron One により返却されたことを確認します。

    前の演習では、図書館アプリケーションのテスト中に、Patron OneBook Nine を返却してもらいました。 アプリケーションで Book NinePatron One によって返却されていないと示されている場合は、入力オプションを使用して Book Nine を選択して返却してから続行してください。

    Library.Console.csproj ファイルを使用すると、アプリケーションのビルド時に JSON データ ファイルが出力ディレクトリに確実にコピーされます。 ただし、クリーンまたはリビルド操作を実行すると、本質的にデータがリセットされます。 ビルド操作を繰り返し実行した場合、出力ディレクトリ (/bin/Debug/net8.0/) のデータはリセットされません。

  9. "Input Options" プロンプトで「b」と入力し、Enter キーを押します。

  10. Book Nine」と入力し Enter キーを押します。

  11. 書籍が貸出可能であることを示すメッセージがアプリケーションに表示されることを確認します。

  12. "Input Options" プロンプトで「q」と入力し、Enter キーを押します。

  13. デバッグ セッションを停止します。

  14. Loans.json ファイルを開きます。

    Loans.json ファイルは、各書籍の貸出の状態を追跡するために使用されます。 Loans.json ファイルを使用して、Book One と Book Nine の在庫の状態が正しいことを確認できます。

    更新された Loans.json ファイルは、Library.Console\bin\Debug\net8.0\Json フォルダーまたは Library.Console\Json フォルダーのいずれかにあります。

    • Visual Studio Code デバッガーを使用してアプリを実行している場合は、更新された Loans.json ファイルは Library.Console\bin\Debug\net8.0\Json フォルダーにあります。

    • dotnet run フォルダーの AccelerateDevGitHubCopilot\src\Library.Console> コマンドを使用してアプリを実行する場合は、更新された Loans.json ファイルは Library.Console\Json フォルダーにあります。

  15. 貸出 ID 37 と貸出 ID 46 が両方とも Book One ("BookItemId": 1) のものであることを確認します。

    • 貸出 ID 37 には ReturnDate 値 (2024-01-17) があるはずです
    • 貸出 ID 46 には、ReturnDate 値がないはずです。 ReturnDate 値は null である必要があります。

    ReturnDate 値は、書籍が現在貸出中かどうかを判断するために使用されます。 ReturnDate 値が null の場合、書籍は貸出中と見なされます。

  16. 貸出 ID 22 が Book Nine ("BookItemId": 9) 用であり、ReturnDate の値が今日の日付に設定されていることを確認します。

    デバッガーで実行していて、Loans.json ファイルに変更を加えた後にソリューションをクリーンした場合、それらの変更は失われます。 ソリューションをクリーンすると、次にアプリケーションを実行するときに、Loans.json ファイルが元のデータにリセットされます。 Loans.json ファイルを手動で更新して、Book One と Book Nine の在庫の状態をテストできます。

変更をメイン ブランチにマージする pull request を作成する

あなたは、図書館司書が書籍の在庫状態を判断できるようにする新機能を完成させました。 ここで、変更をリポジトリのメイン ブランチにマージする必要があります。 変更をメイン ブランチにマージする pull request を作成できます。

以下の手順に従って、演習のこのセクションを完了します。

  1. Web ブラウザーで GitHub リポジトリを開きます。

  2. [pull request] タブを開きます。

  3. [New pull request](新しい pull request) を選択します。

  4. [変更の比較] で、main ブランチに base が構成されていることを確認します。

  5. [比較]book-availability ブランチ用に構成されていることを確認します。

    ブランチを構成すると、mainbook-availability の間の変更の比較が表示されます。 更新した各ファイルの変更内容が表示されます。

  6. [pull request の作成] を選択します。

  7. pull request のタイトルと説明を入力します。

    次のタイトルと説明を使用できます。

    • タイトル: 機能:ConsoleApp に書籍の検索機能を追加する
    • [説明]: この pull request は、図書館司書が書籍の在庫の状態を判断できるようにする新しい機能を追加します。 この機能には、SearchBooks の新しい CommonActions アクション、 WriteInputOptionsReadInputOptionsPatronDetailsConsoleApp メソッドの更新が含まれているほか、SearchBooks に新しい ConsoleApp メソッドが追加されます。

    GitHub Copilot Enterprise のサブスクリプションを持つ企業のメンバーは、GitHub Copilot を使用して、GitHub.com での pull request の概要を生成できます。 概要を使用すると、レビュー担当者に変更を把握してもらったり、レビューしている pull request の変更をすばやく把握したりするのに役立ちます。 [GitHub Actions] を選択し、[概要] を選択して、pull request の概要を生成します。

    GitHub Copilot Enterprise アカウントを使用して生成された pull request の概要の例を次に示します。

    GitHub Copilot Enterprise アカウントを使用して生成された pull request の概要を示すスクリーンショット。

  8. タイトルと説明にコードの更新が反映されていることを確認し、[pull request の作成] を選択します。

  9. チェックが完了するのを待ってから、すべてのチェックに合格し、ベース ブランチとの競合がないことを確認します。

    チェックが完了するまでに 1 分かかる場合があります。 変更をメイン ブランチにマージする前に、特定された問題に対処する必要があります。

  10. 変更をメイン ブランチにマージするには、[pull request をマージする] を選択し、[マージの確認] を選択します。

    変更をマージした後、book-availability ブランチを削除できることに留意してください。

  11. Visual Studio Code を開きます。

  12. リポジトリの main ブランチに切り替えます。

  13. リモート リポジトリから変更をプルします。

  14. book-availability ブランチに加えた変更が、main ブランチに含まれていることを確認します。