📝

トランザクションスクリプト

に公開

トランザクションスクリプトについての簡単な説明と個人的な見解とか。

簡単な解説

https://www.martinfowler.com/eaaCatalog/transactionScript.htmls

簡単に言うと、オブジェクト指向ではなく手続き型のように処理を記載するような感じです。  
その処理で使用されるロジックはそのままその処理中に記載されていきます。  
(汎用的な処理があればそれは別途分割)
APIで受け取ったパラメータクラスやDBとのやりとりで使用するデータクラスに対しての処理を直接ControllerやServiceで記載していくイメージです。

public class UserController {
  public User updateUser(RequestParameter request) {
    // requestパラメータの内容チェック処理
    if (~) {
    }
    ……
    var result = userService.updateUser(request.updateUser);
    return result;
  }
}

public class UserService {
  public User updateUser(UpdateUser updateUser) {
    // DBに渡す前に何かしら処理とか
    var dto = userUtil.convertUser(updateUser);
    ……
    var result = database.updateUser(dto);

    var response = new UpdateUser();
    response.hoge = response.hoge;
    return response;
  }
}

public class UserUtil {
  public UserDTO convertUser(UpdateUser user) {
    var dto = new UserDTO();
    dto.hoge = user.hoge;
    dto.date = convertString(user.date);
    ……
    return dto;
  }
}

利点

利点であげられるのがシンプルなことです。

設計した処理の流れをそのまま各層で実装していけばいいので、実装も単純です。  
処理が大きくなるようならそれ毎に関数に分割すればある程度は見やすくなるので、そのあたり意識すれば複雑さは抑えられるのかと思います。  
サーバーの役割がDBのデータの出し入れ程度で、凝ったドメイン固有のロジックが無いようなケースでは十分選択できるパターンとなります。

欠点

もちろん欠点もあります。  
データとそれに対する処理が分離するため、処理の重複が発生してしまいます。  
例えばユーザーの名前は100文字までという仕様があった場合、ユーザーの情報を扱うAPIが複数あると、そのController毎に同様のif文を追加することになるかと思います。  
また、Serviceクラスも責務がはっきりしていないため、コード量が多く複雑なクラスになりがちです。

個人的な見解

以下個人的な見解です。

よくトランザクションスクリプトでコードが複雑になるようなケースを見かけます。  
ただ実際はトランザクションスクリプトを選択したからコードが複雑になるのではなく、適切に処理の分割や共通化が行えていないため複雑になっているのかと思います。  
(ドメインロジックが複雑な場合はその限りではないと思いますが)

シンプルなため、

  • 経験の浅い人でもそれなりに実装ができる
  • 各役割を分割しようにも、どこに配置すべきかが不明慮(これは層分けなど構成面の問題かとは思いますが)  
    結果、以下のような問題がでてきたりするのかなと。
    • utliフォルダにutilとは言えないようなクラスが大量に作成される
    • Serviceクラスのprivateメソッドに分割した処理が記載され、長大なServiceクラスができあがる
  • すでに実装した処理と同等の処理が他でも必要になった場合、
    • すでにあることを認識していないと重複したコードを書くことになる
    • 認識していても、動いているコードに手を加えたくなくてそのままコピペしてしまう

結局どんなパターンであれ、その時点で最善な設計や責務の分離など行っていく必要があるかと思います。

Discussion