はじめに
こんにちは!アメリカに住みながら独学でソフトウェアエンジニアを目指しているものです。
本日は条件判断の問題を解いたのでそのコードについての振り返りをしていきたいと思います。
勉強記録的な意味合いが強いので見ていただける方がいれば幸いです。
問題の概要
複数のチームメンバーがタスクを管理するシステムを作成してください。タスクには「未着手」「進行中」「完了」「保留」の状態があり、状態に応じた操作や制限が存在します。
要件
- タスクには以下の情報が含まれます:
- タスク名
- 担当者
- ステータス("未着手"、"進行中"、"完了"、"保留")
- 以下の操作を実装してください:
- タスクの開始: 「未着手」状態のタスクのみ「進行中」にできます。
- タスクの完了: 「進行中」のタスクのみ「完了」にできます。
- タスクの保留: 「進行中」のタスクを「保留」にできます。保留中のタスクは再開可能です。
- タスクの削除: 「未着手」または「完了」のタスクのみ削除できます。
- 担当者ごとにタスクを管理し、タスク一覧を表示する機能を実装してください。
- タスクの状態は以下のように遷移します:
- 「未着手」→「進行中」
- 「進行中」→「完了」
- 「進行中」→「保留」
- 「保留」→「進行中」
クラス設計
- Taskクラス: タスクの情報と状態を管理。
- TeamMemberクラス: チームメンバーと担当タスクを管理。
- TaskManagerクラス: タスクの追加、状態変更、削除、一覧表示を管理。
実装例
# タスクの作成
task1 = Task.new("Write Report", TeamMember.new("Takeshi"))
task2 = Task.new("Fix Bug", TeamMember.new("Alex"))
task3 = Task.new("Prepare Presentation", TeamMember.new("Takeshi"))
# チームメンバーの作成
member1 = TeamMember.new("Takeshi")
member2 = TeamMember.new("Alex")
# タスクの管理
manager = TaskManager.new
manager.add_task(task1, member1)
manager.add_task(task2, member2)
manager.add_task(task3, member1)
# タスクの状態変更
manager.start_task(task1) # 「未着手」→「進行中」
manager.complete_task(task1) # 「進行中」→「完了」
manager.hold_task(task2) # 「未着手」のため、保留不可
manager.start_task(task2) # 「未着手」→「進行中」
manager.hold_task(task2) # 「進行中」→「保留」
manager.resume_task(task2) # 「保留」→「進行中」
# タスクの削除
manager.delete_task(task1) # 削除成功(完了済み)
manager.delete_task(task2) # 削除失敗(進行中)
# タスク一覧の表示
manager.list_tasks
上記の問題の回答例
AIを用いて解答例を作成しました。(追記 修正後のコードは以下に記述)
class Task
attr_accessor :name, :assignee, :status
def initialize(name, assignee)
@name = name
@assignee = assignee
@status = "未着手" # 新しいタスクはすべて未着手
end
end
class TeamMember
attr_accessor :name, :tasks
def initialize(name)
@name = name
@tasks = []
end
def add_task(task)
tasks << task
end
end
class TaskManager
def initialize
@tasks = []
end
def add_task(task, member)
# タスクをメンバーに割り当て
member.add_task(task)
# タスクマネージャー内にも記録
@tasks << task
puts "タスク「#{task.name}」が担当者「#{member.name}」に追加されました"
end
def start_task(task)
if task.status == "未着手"
task.status = "進行中"
puts "タスク「#{task.name}」が進行中になりました"
else
puts "タスク「#{task.name}」は未着手でないため、開始できません"
end
end
def complete_task(task)
if task.status == "進行中"
task.status = "完了"
puts "タスク「#{task.name}」は完了しました"
else
puts "タスク「#{task.name}」は進行中でないため、完了できません"
end
end
def hold_task(task)
if task.status == "進行中"
task.status = "保留"
puts "タスク「#{task.name}」は保留になりました"
else
puts "タスク「#{task.name}」は進行中でないため、保留にできません"
end
end
def resume_task(task)
if task.status == "保留"
task.status = "進行中"
puts "タスク「#{task.name}」は再開され、進行中になりました"
else
puts "タスク「#{task.name}」は保留でないため、再開できません"
end
end
def delete_task(task)
if task.status == "未着手" || task.status == "完了"
@tasks.delete(task)
task.assignee.tasks.delete(task)
puts "タスク「#{task.name}」が削除されました"
else
puts "タスク「#{task.name}」が未着手または完了でないため、削除できません"
end
end
def list_tasks
puts "\n=== タスク一覧 ==="
@tasks.each { |task| puts task }
puts "=================\n\n"
end
end
# チームメンバーの作成
member1 = TeamMember.new("Takeshi")
member2 = TeamMember.new("Alex")
# タスクの作成
task1 = Task.new("Write Report", member1)
task2 = Task.new("Fix Bug", member2)
task3 = Task.new("Prepare Presentation", member1)
# タスクの管理
manager = TaskManager.new
manager.add_task(task1, member1)
manager.add_task(task2, member2)
manager.add_task(task3, member1)
# タスクの状態変更
manager.start_task(task1) # 「未着手」→「進行中」
manager.complete_task(task1) # 「進行中」→「完了」
manager.hold_task(task2) # 「未着手」のため、保留不可
manager.start_task(task2) # 「未着手」→「進行中」
manager.hold_task(task2) # 「進行中」→「保留」
manager.resume_task(task2) # 「保留」→「進行中」
# タスクの削除
manager.delete_task(task1) # 削除成功(完了済み)
manager.delete_task(task2) # 削除失敗(進行中)
# タスク一覧の表示
manager.list_tasks
一見問題なさそうなコードですが、以下の点について問題があります。
それはタスクとチームメンバーの紐づけが二重で行われているということです。
Task.newでタスクに担当者を設定し、TaskManager#add_taskでも担当者にタスクを追加しています。
これにより、タスクと担当者の関連付けが二重に行われ、整合性が崩れやすくなっています。
また、p task1
で中を見てみるとtask1の中の担当者(assignee)はTakeshiであり、member1と紐づけているのですが、
その中の@tasksが空となりそれぞれの整合性がとれていません。
# task1の中身
task1--- @name = "Write Report"
|
|_@assignee-------@name = "Takeshi"
| |
|_@status |_@tasks =[] #task1の担当者はTakeshiなのに
上記のコードを改善したもの
Taskの初期値には担当者を設定せず、add_taskメソッドのみで担当者とタスクを関連付けるようにしています
class Task
attr_accessor :name, :assignee, :status
def initialize(name)
@name = name
@assignee = nil
@status = "未着手" # 新しいタスクはすべて未着手
end
def to_s
assignee_name = assignee ? assignee.name : "未割り当て"
"#{name} (担当者: #{assignee_name}, 状態: #{status})"
end
end
class TeamMember
attr_accessor :name, :tasks
def initialize(name)
@name = name
@tasks = []
end
def add_task(task)
tasks << task
end
end
class TaskManager
def initialize
@tasks = []
end
# タスクを担当者に割り当て、整合性を保つ
def add_task(task, member)
# タスクに担当者を設定
task.assignee = member
# 担当者にタスクを追加
member.add_task(task)
# TaskManagerのリストにもタスクを追加
@tasks << task
puts "タスク「#{task.name}」が担当者「#{member.name}」に追加されました"
end
def start_task(task)
if task.status == "未着手"
task.status = "進行中"
puts "タスク「#{task.name}」が進行中になりました"
else
puts "タスク「#{task.name}」は未着手でないため、開始できません"
end
end
def complete_task(task)
if task.status == "進行中"
task.status = "完了"
puts "タスク「#{task.name}」は完了しました"
else
puts "タスク「#{task.name}」は進行中でないため、完了できません"
end
end
def hold_task(task)
if task.status == "進行中"
task.status = "保留"
puts "タスク「#{task.name}」は保留になりました"
else
puts "タスク「#{task.name}」は進行中でないため、保留にできません"
end
end
def resume_task(task)
if task.status == "保留"
task.status = "進行中"
puts "タスク「#{task.name}」は再開され、進行中になりました"
else
puts "タスク「#{task.name}」は保留でないため、再開できません"
end
end
def delete_task(task)
if task.status == "未着手" || task.status == "完了"
@tasks.delete(task)
task.assignee.tasks.delete(task) if task.assignee
puts "タスク「#{task.name}」が削除されました"
else
puts "タスク「#{task.name}」が未着手または完了でないため、削除できません"
end
end
def list_tasks
puts "\n=== タスク一覧 ==="
@tasks.each { |task| puts task }
puts "=================\n\n"
end
end
# チームメンバーの作成
member1 = TeamMember.new("Takeshi")
member2 = TeamMember.new("Alex")
# タスクの作成(担当者はここではまだ設定しない)
task1 = Task.new("Write Report")
task2 = Task.new("Fix Bug")
task3 = Task.new("Prepare Presentation")
# タスクの管理(ここでタスクと担当者を関連付ける)
manager = TaskManager.new
manager.add_task(task1, member1)
manager.add_task(task2, member2)
manager.add_task(task3, member1)
# タスクの状態変更
manager.start_task(task1) # 「未着手」→「進行中」
manager.complete_task(task1) # 「進行中」→「完了」
manager.hold_task(task2) # 「未着手」のため、保留不可
manager.start_task(task2) # 「未着手」→「進行中」
manager.hold_task(task2) # 「進行中」→「保留」
manager.resume_task(task2) # 「保留」→「進行中」
# タスクの削除
manager.delete_task(task1) # 削除成功(完了済み)
manager.delete_task(task2) # 削除失敗(進行中)
# タスク一覧の表示
manager.list_tasks
まとめ
今回はタスク管理システムの作成を通じて、クラス間でどのように情報を管理するか、タスクの状態に応じた操作をどう扱うかを学びました。add_task
やdelete_task
の処理が複雑に感じましたが、コードを読み進めることで各クラスの責任とタスクの流れを理解できました。
理解をしている内に再度復習もして自分の実力していきたいと思いました。