1
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?

社内で仕事をしていると、ふと耳に入ってくる会話があります。

「この処理、そろそろ共通化したほうが良さそうですよね」
「あれ、似たようなのって前に作ってませんでした?」
「CommonUtil 増やしたくないけど……他に置き場がないんですよね」

どれも“良くしよう”という前向きな声ですが、気づけばプロジェクトの片隅で、用途が曖昧な共通クラスがじわじわ増えていきます。名前だけ立派なのに、誰が使っているか分からないクラスたちが、静かに溜まっていくのです。

「共通化しておけば整理になる」
そう信じて始めたはずなのに、気づくとコードはむしろ複雑さを増している──そんな経験はありませんか。

今回は、そんな場面でよく起きる 「共通化はクラス化しようの罠」 についてまとめます。


なぜ「クラス化」したくなるのか

社内でよく聞く声として、こんなやり取りがあります。

「似た処理があるから、どこかにまとめたい」
「コピペを減らすためにも、共通クラスにしよう」
「再利用できる場所に集めたい」

共通化という発想自体は健全です。問題は、その先で 「クラスにまとめる=正義」 と短絡的につながることです。


クラス化によって生まれる「便利そうで便利じゃない場所」

クラスを作ると、整理された印象になります。しかし現実は…

  • 機能の関連が薄いメソッドがひとまとめにされる
  • 「ここに入れるのは違う」と思いながらも他に置き場がない
  • 似た名前のクラスが増え、逆に探しにくくなる

気づけば Common、Util、Helper、Manager…
名前だけ立派な倉庫が増えてしまいがちです。

アンチパターン例:便利クラスにまとめすぎる

public class StringUtils
{
    public string Normalize(string s) {  }
    public string Reverse(string s) {  }
    public bool IsNullOrEmpty(string s) {  }
    public string ToTitleCase(string s) {  }
    // どんどん追加され、クラスが肥大化
}
  • 毎回 new StringUtils() で呼ぶ必要がある
  • どこに何の処理があるか分かりにくい
  • テスト対象が増え、保守性が下がる

また、状態を持たないのにインスタンス変数を持たせるケースもあります。

public class Calculator
{
    private int lastResult;

    public int Add(int a, int b) { lastResult = a + b; return lastResult; }
    public int Multiply(int a, int b) { lastResult = a * b; return lastResult; }
}
  • 処理の意図と状態管理が混ざり、再利用性が低下
  • 「計算の手順」と「状態」を分けて考えられなくなる

本来の共通化に必要なのは、“クラス化”ではなく“モデリング”

大事なのは 「同じ処理だからまとめる」ではなく、同じ概念だから同じ場所にいるべき」 という視点です。

  • この処理はどんな文脈で生まれたか
  • 何を表しているのか
  • どんなデータや振る舞いと結びついているか

クラス名を見て役割が分かるか

曖昧な共通クラスは、後々「何を担当してるんだっけ?」と迷惑な存在になりがちです。
逆に、モデリングとして意味がある場合は、同じ処理が複数あっても 共通化しない方が読みやすいこともあります。


クラス化すべきかどうかの判断基準

現場で私が使うのは以下の3点です。

1. 状態(データ)とセットで意味があるか
単なる作業手順ではなく、データと振る舞いが自然な関係を持っているか。
2. クラス名から“役割”が思い浮かぶか
名前を見て「何をするクラスか」を説明できるなら存在理由がある。
3. そのクラスは“文脈の中で”必要か
その領域(ドメイン)に属していると言えるかどうか。

この3つのどれもクリアしなければ、クラス化は一度立ち止まるサインです。


クラス化が不要なケースに気づくヒント

「同じ処理だから共通化したい」と思ったときは少し視点を変えてみましょう。

ローカルメソッドで十分では?

拡張メソッドに逃す方が読みやすいのでは?

本来のクラスに自然に吸収できないか?

構造的に共通化しない方が理解しやすい場合もあります。
共通化は “減らす方向”で考える と、コードの密度が驚くほど落ち着きます。


改善例 :クラス化せずに共通化する方法

1. 拡張メソッドで共通処理を整理

public static class StringExtensions
{
    public static string Normalize(this string s) =>
        s?.Trim().ToUpper();

    public static bool IsNullOrEmpty(this string s) =>
        string.IsNullOrEmpty(s);

    public static string ToTitleCase(this string s) =>
        CultureInfo.CurrentCulture.TextInfo.ToTitleCase(s.ToLower());
}

// 利用例
string name = "  itabashi  ";
string normalized = name.Normalize();
bool empty = name.IsNullOrEmpty();
string title = name.ToTitleCase();
  • 状態を持たないのでインスタンス不要
  • 用途ごとにファイル分けすれば肥大化防止
  • 可読性と保守性が向上

2. ローカル関数や関数化で簡単に再利用

int Add(int a, int b) => a + b;
int Multiply(int a, int b) => a * b;

int sum = Add(3, 4);
int product = Multiply(3, 4);
  • 簡単な処理はローカル関数で十分
  • 不要なクラスを増やさずに済む

まとめ

  • 「共通化=クラス化」ではない
  • 大事なのは 「モデリング視点で整理すること」
  • クラス化すべきかどうかは 状態・役割・文脈 で判断
  • 共通化は 減らす方向で考えるとコードの密度が落ち着く
  • 共通化の本質は「整理すること」ではなく「概念や文脈に沿った再利用」です。

短絡的にクラス化する前に、一度立ち止まって考えてみましょう。

1
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
1
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?