ここから第19回までで、保存できるタスク管理CLIを完成させます。前提は第01〜16回です。CLIはコマンドラインから操作するプログラムです。
作るものを小さく確定する
操作はadd、list、doneの三つです。タスクは正のID、空でない題名、完了状態を持ちます。完了済みを再び完了にしても成功し、存在しないIDはエラーにします。保存ファイルがなければ空から始め、壊れていれば勝手に空として上書きしません。同時に複数のプロセスから更新する用途は、この実習の対象外です。
まず新しいフォルダにTask.javaを作ります。このファイルは単体の実行プログラムではなく、次回のTaskAppから使うモデルです。
public record Task(int id, String title, boolean done) {
public Task {
if (id <= 0) throw new IllegalArgumentException("IDは正の整数です");
if (title == null) throw new IllegalArgumentException("題名がありません");
title = title.strip();
if (title.isEmpty() || title.length() > 200 ||
title.contains("\t") || title.contains("\n") || title.contains("\r")) {
throw new IllegalArgumentException("題名は改行・タブなしの1〜200 UTF-16単位です");
}
}
public Task complete() {
return new Task(id, title, true);
}
}
このモデルは生成時に不変条件を検査します。completeは元の値を変更せず、完了状態の新しいTaskを返します。ファイルから復元するときにも同じコンストラクタを使えば、入力方法によって検査が抜けることを防げます。
保存形式も仕様にする
一行を「ID、タブ、0または1、タブ、題名」とするUTF-8のTSVを使います。題名にタブと改行を禁止したのは、この簡単な形式が曖昧にならないためです。自由な改行を保存したくなったら、場当たり的に置換するのでなく、JSONなどエスケープの定義された形式を検討します。
受け入れ条件は、追加後の一覧、再起動後の一覧、完了後の表示、無効入力で保存内容が変わらないことです。この四つを先に書き出してから実装します。操作説明も実装の後回しにしません。
練習と解答
練習:削除機能を追加したとき、次のIDを単に「件数+1」にすると何が起きますか。
解答:ID1と3が残る二件の状態で3を発行し、重複します。この実習は最大ID+1を使います。ただし末尾を削除してもIDを再利用しない要件なら、別に発番情報を永続化する必要があります。IDの一意性と、一度使った値を永久に再利用しないことは異なる要件です。
公式資料
recordをモデル設計の参照先にできます。
Java全20回の目次 | 前の回 | 次の回