eラーニングプラットフォーム
CoddyのGOジャーニー「オブジェクト指向プログラミング」セクションの一部 — レッスン 105/107。
チャレンジ
簡単コースや学生を管理し、学習の進捗を追跡するEラーニングプラットフォームを構築しましょう!構造体、インターフェース、コンポジション、ポリモーフィズムを組み合わせて、学生がコースに登録し、レッスンを完了できるまとまりのあるシステムを作成します。
コードは5つのファイルに整理します:
lesson.go: 個々の学習単位を表すLesson構造体を定義します。各レッスンにはID、Title、およびDuration(分単位)があります。Lesson へのポインタを返すNewLessonコンストラクタを含めます。course.go:ID、Title、Instructor、および*Lessonポインタのスライスを含むCourse構造体を作成します。NewCourseコンストラクタとAddLessonメソッドを含めます。また、コース内のすべてのレッスンの所要時間の合計を返すTotalDuration() intメソッドも実装します。student.go:ID、Name、およびEmailフィールドを持つStudent構造体を定義します。NewStudentコンストラクタを含めます。enrollment.go: ここで進捗追跡の魔法が起こります。学生とコースをリンクし、完了したレッスンを追跡するEnrollment構造体を作成します。以下を持つ必要があります:StudentへのポインタCourseへのポインタCompletedLessonsマップ(レッスンIDからブール値へのマッピング)
パーセンテージ(0.0 から 100.0)を返す
Progress() float64メソッドを持つProgressableインターフェースを定義します。Enrollment に以下のメソッドを実装します:
NewEnrollment(student *Student, course *Course) *Enrollment— 空の完了済みレッスンマップを初期化するコンストラクタCompleteLesson(lessonID string) string— レッスンを完了としてマークします。レッスンがコースに存在しない場合はlesson not foundを返し、すでに完了している場合はalready completedを返し、成功した場合はcompletedを返します。Progress() float64— 完了したレッスンの割合(完了数/合計 * 100)を返します。コースにレッスンがない場合は 0.0 を返します。
main.go: プラットフォームを構築し、登録操作を処理します。コースのID、タイトル、インストラクターを読み取ります。次に、レッスンの数と、各レッスンのID、タイトル、所要時間を読み取ります。学生のID、名前、メールアドレスを読み取ります。学生とコースをリンクする登録(enrollment)を作成します。
次に、操作の数を読み取ります。各操作は
complete [lessonID]またはprogressのいずれかです。complete 操作の場合は、結果メッセージを出力します。progress 操作の場合は、小数点以下1桁にフォーマットされた進捗状況にパーセント記号を続けて出力します。
以下の入力が提供されます:
- コースID、タイトル、インストラクター(3行)
- レッスンの数、次に各レッスンのID、タイトル、所要時間(各3行)
- 学生ID、名前、メールアドレス(3行)
- 操作の数、次に各操作(各1行)
例えば、以下の入力が与えられた場合:
C001
Go Fundamentals
Jane Smith
3
L001
Variables
30
L002
Functions
45
L003
Structs
60
S001
Alice
alice@learn.com
5
progress
complete L001
progress
complete L001
complete L002出力は次のようになります:
0.0%
completed
33.3%
already completed
completedまた、以下の入力が与えられた場合:
C100
Python Basics
Bob Teacher
2
L100
Intro
20
L101
Loops
40
S100
Charlie
charlie@edu.com
4
complete L999
complete L100
complete L101
progress出力は次のようになります:
lesson not found
completed
completed
100.0%Enrollment 構造体がコンポジションを使用して学生とコースをリンクしているのに対し、Progressable インターフェースは任意の型がその完了ステータスを報告できるようにしていることに注目してください。この設計により拡張が容易になります。同じインターフェースを使用して、個々のレッスンや学習パス全体に進捗追跡を追加することができます!
自分で試してみよう
package main
import (
"bufio"
"fmt"
"os"
"strconv"
"strings"
)
func main() {
scanner := bufio.NewScanner(os.Stdin)
// 1行を読み込むためのヘルパー関数
readLine := func() string {
scanner.Scan()
return strings.TrimSpace(scanner.Text())
}
// コース情報を読み込む
courseID := readLine()
courseTitle := readLine()
courseInstructor := readLine()
// TODO: NewCourse を使用してコースを作成する
_ = courseID
_ = courseTitle
_ = courseInstructor
// レッスン数を読み込む
numLessons, _ := strconv.Atoi(readLine())
// TODO: 各レッスンを読み込み、コースに追加する
for i := 0; i < numLessons; i++ {
lessonID := readLine()
lessonTitle := readLine()
lessonDuration, _ := strconv.Atoi(readLine())
// TODO: レッスンを作成し、コースに追加する
_ = lessonID
_ = lessonTitle
_ = lessonDuration
}
// 受講生情報を読み込む
studentID := readLine()
studentName := readLine()
studentEmail := readLine()
// TODO: NewStudent を使用して受講生を作成する
_ = studentID
_ = studentName
_ = studentEmail
// TODO: 受講生とコースを紐付ける登録(enrollment)を作成する
// 操作の数を読み込む
numOps, _ := strconv.Atoi(readLine())
// 各操作を処理する
for i := 0; i < numOps; i++ {
operation := readLine()
if operation == "progress" {
// TODO: Progress() を呼び出し、"%.1f%%" の形式で出力する
fmt.Println("0.0%") // 実際の進捗状況に置き換える
} else if strings.HasPrefix(operation, "complete ") {
lessonID := strings.TrimPrefix(operation, "complete ")
// TODO: CompleteLesson を呼び出し、結果を出力する
_ = lessonID
fmt.Println("") // 実際の結果に置き換える
}
}
}
オブジェクト指向プログラミングのすべてのレッスン
1Go オブジェクト指向の基礎
外部ファイルGo ワークスペースとモジュールパッケージとインポート公開された名前と非公開の名前Go におけるオブジェクト指向入門クラスとしての構造体構造体へのメソッド定義ポインタレシーバと値レシーバ構造体の初期化コンストラクタ関数まとめ:簡易計算機8エラー処理とOOP
error インターフェースカスタムエラー型エラーラッピング (fmt.Errorf)センチネルエラーerrors.Is() と errors.As()Panic、Defer、Recover復習 - ファイルパーサー