0
0

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

タスク管理のデータ構造 - JSONLとUUIDの選択 - Day 4

0
Last updated at Posted at 2026-05-05

はじめに

Day 3では、時間記録機能の設計とパス指定にまつわる失敗について書きました。

今回はタスク管理機能のデータ構造について書きます。保存形式の選定・UUIDによるタスク識別・ステータス設計と、将来のNN機能との連携を見据えた判断が積み重なった部分です。


機能概要

タスク管理機能は、目標を登録しステータスを割り振ることで進行度を管理する目的で実装しています。

ステータスは未着手・進行中・完了の3種類です。このステータスとタスク情報をNN機能で読み込むことで、プロジェクト全体の状況を把握しつつ完成時期予測を行うことを想定しています。


保存形式にJSONLを選んだ理由

保存形式にはJSONLを採用しています。

JSONLは1行が1つのJSONデータで構成される形式です。タスク1件を1レコードとして追記していく構造が、NN機能での読み込みに適していると判断しました。

時間記録にCSVを使用しているのと対照的ですが、これは用途の違いによる使い分けのためです。時間記録は単純な行追記で完結しますが、タスク情報はUUID・期限・ステータス・完了日時といった複数の属性を持つ構造化データです。CSVより柔軟にフィールドを持てるJSONLがこの用途に適しています。

実際のレコードは以下のような構造になっています。

{
  "key": "1cf3104c-ff8f-4178-9727-670375c6894f",
  "created_at": "2026-05-04",
  "limit": "2025-5-5",
  "task": "UUIDによるレコード管理実装",
  "status": 0,
  "updated_at": "2026-05-04"
}

UUIDによるタスク識別

タスクの識別にはUUIDを採用しています。

連番IDではなくUUIDを選んだ理由は、タスクごとに期限・開始日時・ステータス更新日時を独立して管理するためです。連番IDは生成順序に依存するため、タスクの追加・削除が繰り返されると整合性の管理が複雑になります。UUIDであれば生成順序に関係なく各タスクを一意に識別できます。

また、将来的にNN機能がタスクデータを参照する際、IDが順序に依存しない設計の方が扱いやすいという側面もあります。

保存処理の該当部分は以下の通りです。

for i in entry:
    recode_id = str(uuid.uuid4())
    if i == "":
        continue

    self.goals = {'key': recode_id,'created_at': i[0],"limit": self.limit, 
            'task': i[1], "status": -1, "updated_at": None}
    
    if not os.path.exists(create_path('json/')):
        os.mkdir(create_path('json/'))
    
    with open(self.json_file, 'a', encoding='utf-8') as f:
        data = json.dumps(self.goals, ensure_ascii=False)
        f.write(data + "\n")

タスク登録時にuuid.uuid4()でIDを生成し、keyフィールドに格納しています。初期ステータスは-1(進行中)で固定されます。


ステータス設計

各タスクのステータスは数値で管理しています。

意味
-1 進行中
0 未着手
1 完了

ステータスが1(完了)になった場合は、以降の更新を受け付けない設計にしています。完成時期予測の精度を保つためと、完了済みタスクのステータスが後から変更されないようにするためです。

ステータス更新時のバリデーションと更新処理は以下の通りです。

if self.status.lstrip('-').isdigit():
    self.status = int(self.status)
# check
if isinstance(self.status, str):
    return "ステータス更新時に文字列が送られました"

if self.status > 1 or self.status < -1:
    return "ステータス更新時に不正な値が送られました"

# 完了済みタスクはスキップ
if file_data['status'] == 1:
    print("既に完了済みのタスクです")
    continue

文字列が送られた場合・範囲外の値が送られた場合・完了済みタスクへの更新の3パターンをバリデーションで弾いています。

今後、期限と完了日時の差分から実作業日数を算出する機能の開発を予定しています。この機能とNN機能を組み合わせることで、より正確な完成時期予測を実現することを目標にしています。


おわりに

今日はタスク管理機能のデータ構造について書きました。

JSONLとUUIDの採用はどちらも将来のNN機能との連携を見据えた判断です。現時点では過剰に見えるかもしれませんが、後から設計を変えるコストを考えると最初から整えておく方が合理的だと考えています。

ただ、現在の実装は小タスクの定義が行えない、タスクをプロジェクト単位で管理できないなdの問題もあるため、今後の開発において全面改修を予定しています。改修が完了した段階で別途記事にまとめます。

Day 5では、FastAPIによるAPIハブの設計について書く予定です。フロントエンドとバックエンドの責務分離をどのように実現しているか、エンドポイントの設計判断を記録します。

リポジトリはOSS公開準備中です。公開後にこの記事へリンクを追加します。


この記事は連載「クラウドに依存しないマイルストーン管理ツール開発記」のDay 4です。

0
0
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
0
0

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?