🔦

Utilsを徹底活用する――境界・命名・構成・実装・運用の実務指針

に公開

Utilsを あえて"徹底して使いこなす" ための整理。
目的は 可読性・再利用性・テスト容易性を両立すること。
そのために 境界を明確化し、命名と構成で「“何でも箱”」化を避け、実装と運用ルールで品質を担保します。

0. 結論

  • 役割で分割された“小さな utils”を複数置く(例:utils/text.py, utils/time_.py, utils/pathing.py
  • utils の名称にはドメイン語彙を入れない。ドメインは値オブジェクト/サービスとして集約する
  • 純粋関数中心メモ化・事前コンパイルなどの性能小技utils に集約する
  • ガードレール(命名・依存・テスト・計測)を明文化し、PR レビューと CI で自動チェックする

前提:本稿の実装例は Python ベースです。ただし原則は言語非依存であり、他言語でもツール名・文法を置き換えて適用可能と考えています。

Utils と関数設計

utils に含める関数は「純粋で決定的」であることが望ましい。
これは コマンドクエリ分離原則(CQS) の実践と相性がよい。

  • コマンド:状態を変える(副作用を持つ)処理
  • クエリ:値を返す処理

utilsクエリに限定し、コマンドはドメイン/アプリケーション層に配置することで、予測可能・テスト容易・再利用しやすい形を保てる。

1. utils 利用にあたる目的とスコープ

目的

  • 横断的・技術的な処理(文字列、日時、パス、正規表現、軽量変換)を再利用し、設計をシンプルに保つ
  • 実装標準(例:正規化・丸め・フォーマット)を一元化し、意図のばらつきを抑制する

スコープ(utils に含めて良いもの)

  • ドメイン非依存の純粋処理:I/O なし、同一入力→同一出力
  • 軽量な技術ポリシー:トリミング規則、正規表現、パス規約 等
  • 小さなアダプタ:外界クロック/乱数のインターフェース定義(実体は上位で注入)

スコープ外(入れない)

  • DB/HTTP/FS など外部境界アクセス
  • ドメイン語彙Money, Order, Invoice 等)
  • 大規模状態・グローバル可変データ

2. utils にドメインを含めない理由

utils にドメインを含めると、次の理由で臭いやすくなります

  • 責務が読めないutils という名は意図を隠す
  • 凝集度が下がる:ドメインと技術が混在して肥大化する
  • 依存のハブ化:どこからも参照され循環依存の温床になる
  • 設計の成長阻害:本来は“オブジェクトの振る舞い”や“ポリシー”へ昇格すべき処理が埋もれる

3. 判断フロー:置き場所の優先順位(3 パス)

  1. ドメイン(値オブジェクト/エンティティ)

    • その振る舞いが単一オブジェクトの情報だけで完結するなら、そこへ置く
    • 例:EmailAddress.is_corporate(), Money.add()
  2. ドメインサービス(ステートレス)

    • 複数のドメインオブジェクトにまたがる規則/計算
    • 例:calculate_order_total(order, price_list, tax_policy)
  3. 技術モジュール(“作り方”に特化)

    • ドメイン語彙に依らない純粋処理(文字列整形・日時変換・正規表現など)
    • 例:utils/text.py, utils/time_.py(※ “common / misc / utils”の一枚看板は作らない)

4. 依存と可視化のルール

  • 依存方向
    • domain → utilsOK
    • utils → domainNG(循環依存の回避のため)
  • 公開 API の最小化
    • __all__ でエクスポート対象を制御
    • 内部用は _internal 命名で明示的に非公開化
  • 依存関係の可視化と監視
    • deptry や import グラフ可視化ツールで依存関係を定期レポート
    • 依存元が急増して“ハブ”になり始めたらモジュール分割を検討

5. チーム運用(合意事項の雛形)

  • 命名ルール
    • common / misc / helpers は禁止
    • 役割で名前を限定(例:text, time_, pathing など用途名)
  • 追加 PR の説明責任
    • なぜ utils に置くのか?」を説明する(ドメインでない/I/O しない/純粋で決定的 など)
  • 重複の取り扱い
    • 同種処理が 2 箇所に出たら 抽出
    • ドメインに関わる重複は値オブジェクト/サービスへ、ドメイン非依存の重複のみ utils へ移動
    • モジュールが肥大化したら 用途ごとに再分割
  • CI チェックに組み込む項目
    • mypy(型チェック)
    • ruff / flake8(lint)
    • import cycle 検査
    • カバレッジ閾値の確認

6. まとめ

  • utils を“禁止”せず、破綻しにくい形で活用する指針は構築できる。
  • 成功のカギは、“使い方(ドメイン)ではなく作り方(技術)
  • 命名 / 構成 / 依存 / テスト / 計測のガードレールを設け、PR / CI で継続運用する。

道具箱は「何でも入る」から便利なのではなく、仕切りがあるから取り出しやすい
utils も同様に、仕切り(境界・命名・運用ルール) を設けて利用する。

Discussion