🐥

駆け出しエンジニアほどテスト駆動開発をしたほうが良い

に公開

はじめに

テスト駆動開発(TDD)は
「意識の高い人がやるもの」だと思われがちです。

違います。

理由は単純です。

設計力がまだ育っていないからです。

そしてTDDは、
設計を強制的に良くする仕組みだからです。

テストを書こうとすると、何が起きるか

テストを書こうとすると、必ずこうなります。

  • メソッドを分ける

  • 依存を減らす

  • ロジックを純粋化する

  • staticを避ける

  • 時刻やDBを直接呼ばなくなる

なぜか?

テストできないからです。

テストできないコードの例

public class OrderService
{
    public void Process(Order order)
    {
        var db = new AppDbContext();

        if (order.Amount > 10000)
        {
            order.Discount = order.Amount * 0.1m;
        }

        db.Orders.Add(order);
        db.SaveChanges();
    }
}

テストしようとすると:

  • DbContextが直接newされている

  • 副作用だらけ

  • 戻り値がない

  • ロジックと永続化が混ざっている

つまり、設計が悪い。

TDDをやるとどうなるか

まず最初にテストを書きます。
例として割引の計算ルールのテストを書きます。

[Fact]
public void 10000円以上は10%割引される()
{
    var calculator = new DiscountCalculator();

    var result = calculator.Calculate(10000m);

    Assert.Equal(1000m, result);
}

上記のように実装しました。しかし先ほどのOrderServiceでテストができません。

なぜなら OrderService は 割引計算だけのクラスではない からです。

  • 「割引ロジック」以外の要素が混ざっていて、ルールだけを検証できない

だから下記のように分けます。

ロジックを分離する

public class DiscountCalculator
{
    public decimal Calculate(decimal amount)
    {
        if (amount > 10000)
            return amount * 0.1m;

        return 0;
    }
}

その結果OrderServiceは下記のようになります。

public class OrderService
{
    private readonly DiscountCalculator _calculator;
    private readonly IOrderRepository _repository;

    public OrderService(
        DiscountCalculator calculator,
        IOrderRepository repository)
    {
        _calculator = calculator;
        _repository = repository;
    }

    public void Process(Order order)
    {
        order.Discount = _calculator.Calculate(order.Amount);
        _repository.Save(order);
    }
}
  • メソッドが分かれた

  • 依存が抽象化された

  • ロジックが純粋化された

  • 副作用が隔離された

自然と設計が良くなっていると思います。

TDDは、
設計改善を強制するプロセスです。

駆け出しにこそ必要な理由

駆け出しエンジニアは:

  • 責務の分離が甘い

  • 依存を意識できない

  • 副作用を気にしない

  • とりあえず動かす

これは能力の問題ではなく経験が足りないだけです。

TDDをやると、

設計を考えざるを得ない。

だから成長が加速します。

まとめ

テスト駆動開発は、

  • バグを減らすため

  • カバレッジを上げるため

  • 意識を高めるため

ではありません。

駆け出しエンジニアほど、

まずテストを書いてください。

その過程で、

  • メソッドが分かれ

  • 依存が減り

  • ロジックが純粋化し

設計が洗練されていくと思います。

Discussion