設計業務にお詳しい方は読み飛ばして下さい。(もし、おや?と思った方には読んで頂けたら幸いです)
Dart言語の基本的な命名規則は前回記事(以下)を参照頂くとして…
…今回は詳細設計レベルでDB操作処理の命名規則についてです。
1.このお話の前提
いきなり例え話なのですが、DB操作処理につける名前、どうなさっていますか?
「1人でいっきに片づける」という場合はどんな名前でも問題は起きないと思うのですが、複数人(例えば、2グループ(①画面処理側担当、⓷DB処理側担当)や、3グループ(①画面処理側担当、②世話焼き(タスクモデル側)担当、⓷DB処理側担当)等)で開発する場合、(やはり例えばなのですが)③DB側で用意したinsertコマンド(queryコマンドをラップしただけ)があった場合、いきなり①画面処理側担当が、(ただでさえ画面制御でコードが荒れそうなこともあると思うんですよね)この基本的なinsertコマンドを、何か所かの部分で、使用するとなると、(やはり例えば、画面の各々のボタン等で使う場合)コードが複雑になったり、してしまいますよね。故に、②世話焼き(タスクモデル側)担当が、(①画面処理側担当にとって)使いやすいメソッドにラップする、ということが多いと思います。
そうすると、どうなるかというと、似た様な処理が(ただですら)多いのに、上記の2段階、3段階で作成したメソッドが、(言い方は良くないですが)散乱したりして、そうすると、開発メンバーから、「まぎらわしい」という声がでたりします。
(もちろん、各グループの人用のメソッド一覧は準備される(はず)ですが、元々のメソッドに、命名規則はあった方が良い、という観点で、以降のお話に進みます)
2.DB操作処理の命名規則(提案)
DB操作処理が、3層構造(3グループ)と仮定しています。
(話の流れ上、上記とは①~③の順番と、以下の(1)~(3)の順番は逆になっています)
(1) DB側
立場:最もDB本来に備わったコマンドを使用
命名規則:接頭辞に、raw、core 等を付け、直接的なDB操作であることを明示する。
例:rawInsertTask、coreDeleteTask
(2) タスクモデル側
中間で、DB側で作成されているメソッドを、画面処理側が使いやすい様にカスタマイズ
命名規則:接頭辞に、manage、handle 等を付け、操作を抽象化して、よりビジネスロジックに近い操作であることを明示する。
例:manageInsertTask、handleUpdateTask
(3) 画面処理側
簡潔で利用しやすいメソッドを提供されたものを利用
命名規則:接頭辞に、get、set、create、delete 等、最終的なアプリケーションのUIに直接関連する動詞を付ける。
例:createNewTask、deleteTaskById、getTasksForDisplay
3.実用的な理由
上記の様に、直感的に分かり易くする、という理由以外に、以下の様な実用性があります。
(1) 整合性と一貫性
各層の目的に応じた命名規則を採用することで、開発者はどのメソッドが何をするのか、どの層に属しているのかをすぐに理解できます。
(2) 可読性の向上
明確な命名規則は、新しい開発者がコードベースに迅速に慣れるのを助け、既存の開発者が効率的に作業を進めることを可能にします。
(3) メンテナンスの容易さ
適切に命名されたメソッドは、将来の変更や拡張時にどこを修正すればよいかを容易に特定できるため、メンテナンスが容易になります。
これらの命名規則を適用することで、アプリケーションのDB操作関連のコードがより組織的で、扱いやすくなります。
4.具体例
以下、上記にもありましたが、coreメソッド、manageメソッドの具体例です。
(1) DB更新用メソッド例:
// 指定されたテーブルの既存のレコードを更新するために使用されます。
// このメソッドは、成功した場合に更新された行の数を表す int 型の戻り値を返します。
// 使用例:
// int updatedRows = await coreUpdate(
// 'users',
// {
// 'name': '新しい名前',
// 'email': 'newemail@example.com'
// },
// where: 'id = ?',
// whereArgs: [10] // IDが10のユーザーを指定
// );
Future<int> coreUpdate(String table, Map<String, dynamic> data, {String? where, List<dynamic>? whereArgs}) async {
final db = await database;
return await db.update(table, data, where: where, whereArgs: whereArgs);
}
↓
// 特定のカテゴリに属し、削除フラグがONのタスクの中から、
// 特定のタスクだけの削除フラグをOFFに更新(revFlgもOFFに初期化)
Future<int> manageUpdateSoloTaskDelFlag(int taskId, int cateId) async {
// 更新するデータのマップ
Map<String, dynamic> data = {'delFlg': false, 'revFlg': false}; // 削除フラグをOFFに設定, 復元フラグをOFFに設定
// 'tasks' テーブルで特定の taskId を持つ行の delFlg を更新
// この更新は特定のカテゴリに属し、削除フラグが既にONのタスクに限定される
return await _dbHelper.coreUpdate(
'tasks',
data,
where: 'taskId = ? AND cateId = ? AND delFlg = ?', // 更新対象の条件
whereArgs: [taskId, cateId, true] // taskId, cateId, delFlg の値
);