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

📘 Vol.10.8:Service層の共通基盤化とDI対応(テストもしやすく)

Last updated at Posted at 2025-05-25

✅ 本記事の目的

本記事では、前回に続き Service層の設計をさらに強化し、以下を目指します:

  • 複数のServiceで使える「共通基盤」の構築
  • DI(依存性注入)を意識した柔軟でテストしやすい設計
  • モック差し替えによるユニットテストの向上

🧩 1. なぜ共通基盤とDIが必要なのか?

✳️ 問題点(Before)

  • Serviceクラスで同じような DAO呼び出しログ出力, 例外変換処理 が重複しやすい
  • DAOを直に生成(new)しているため、テスト時に差し替えられない
  • コードの再利用性・保守性が低下

✅ 解決策(After)

  • 共通処理を BaseServiceAbstractService にまとめる
  • DAOやユーティリティを DI(依存性注入) で受け取る設計にする
  • テスト時に Mock DAO へ差し替え可能に

🧩 2. Serviceインタフェース+実装クラスの設計パターン

// UserService.java(インタフェース)
public interface UserService {
    User getUserById(int id);
}
java
コピーする
編集する
// UserServiceImpl.java(実装クラス)
public class UserServiceImpl implements UserService {
    private final UserDao userDao;

    // DI(依存性注入)を意識したコンストラクタ
    public UserServiceImpl(UserDao userDao) {
        this.userDao = userDao;
    }

    @Override
    public User getUserById(int id) {
        return userDao.findById(id);
    }
}

✅ ポイント

  • UserService インタフェースが外部公開契約

  • UserServiceImpl は内部の具体実装

  • DAOを「自分でnewせず、外から渡す(DI)」のがコツ


🧩 3. BaseServiceの共通処理を活用する

// BaseService.java(共通処理を持たせる)
public abstract class BaseService {
    protected void log(String msg) {
        System.out.println("[Service Log] " + msg);
    }

    protected RuntimeException wrapException(Exception e) {
        return new RuntimeException("Service層例外:" + e.getMessage(), e);
    }
}

// UserServiceImpl.java(継承して共通処理を活用)
public class UserServiceImpl extends BaseService implements UserService {
    private final UserDao userDao;

    public UserServiceImpl(UserDao userDao) {
        this.userDao = userDao;
    }

    @Override
    public User getUserById(int id) {
        try {
            log("ユーザー取得開始");
            return userDao.findById(id);
        } catch (Exception e) {
            throw wrapException(e);
        }
    }
}


🧪 4. DIによるユニットテストのしやすさ

// UserServiceImplTest.java(JUnitでMock DAOを差し替え)
public class UserServiceImplTest {
    @Test
    public void testGetUserById() {
        // Mock DAOを渡す
        UserDao mockDao = new UserDao() {
            public User findById(int id) {
                User u = new User();
                u.setUserId(id);
                u.setUsername("mockUser");
                return u;
            }
            // 他のメソッドは未使用なので空実装でOK
        };

        UserService service = new UserServiceImpl(mockDao);

        User result = service.getUserById(1);
        assertEquals("mockUser", result.getUsername());
    }
}

✅ ポイント

  • 実際のDBを使わずに動作検証ができる

  • DIの設計にしておくことで、簡単にモック注入できる


🧩 5. DIフレームワークとの連携(将来的に)

💡 Spring導入時のイメージ

@Service
public class UserServiceImpl implements UserService {
    @Autowired
    private UserDao userDao;

    ...
}

☑️ 将来Springなどを導入する際もDI設計にしておけば移行しやすい


✅ まとめ:Vol.10.x シリーズの設計がつながる

内容
DTO データの受け渡しモデル(Vol.10.1)
DAO DBとの直接のやり取り(Vol.10.2~10.3)
Action UI層との橋渡し(Vol.10.4)
Service ロジック集中・DAO統合(Vol.10.6~10.8) ←いまここ!

✨ シリーズまとめ(Vol.10.x バリデーション編)


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