参考
各レイヤー
1. Entities
- ビジネスルールをカプセル化したもの
- ドメイン
- 運送アプリだったら、運送の世界がオブジェクト
2. Use Cases
- ビジネスを表現したオブジェクト
- 買い物するときの受注だったり購入。カートがEntities。
3.Interface Adapters
- Controllers, Presenters, Gatewaysに分けられる。
- ゲームでいう、コントローラとかディスプレイ
4. Frameworks & Drivers
- 詳細なコード
- ビジネスロジックがこれに依存しないようにする
それぞれの関係を図に表すと
処理の流れ
より詳細な処理の流れ
実装例 (サンプル: ユーザー作成機能)
1. Controller
public class UserController {
@Inject
private UserAddUseCase addUserCase;
public void createUser(String name, String roleId) {
UserRole role = convertRole(roleId);
// アプリケーションが求めるデータに変換する
UseAddInputData inputData = new UserAddInputData(name, role);
addUseCase.handle(inputData);
}
private UserRole convertRole(String roleId) {
switch (roleId) {
case "admin": return UserRole.ADMIN;
case "member": return UserRole.MEMBER;
default: throw new RuntimeException();
}
}
}
2. Input Data ※DTOと一緒
public class UserAddInputData implements InputData<UserAddInputData> {
private final String userName;
private final UserRole role;
public UserAddInputData(String userName, UserRole role) {
this.userName = userName;
this.role = role;
}
public String getUserName() { return userName; }
public UserRole getUserRole() { return role; }
}
3. Input Boundary
public interface UserAddUseCase {
void handle(UserInputData inputData);
}
4. Use Case Interator
@Transactional
public class UserAddInterator implements UserAddUseCase {
@Inject
private UserRepository userRepository;
@Inject
private UserAddPresenter userAddPresenter;
@Override
public void handle(UserInputData userInputData) {
String uuid = UUID.randomUUID().toString();
User user = new User(
new UserId(uuid),
new UserName(inputData.getUserName()),
inputData.getRole()
);
userRepository.save(user);
UserAddOutputData outputData = new UserAddOutputData(uuid);
userAddPresenter.output(outputData);
}
}
5. Data Access Interface
public interface UserRepository {
public void save(User user);
public void remove(User user);
public List<User> findAll();
public Optional<User> find(UserId id);
}
6. Data Access
- サンプルはEBean
- 実装は直打ちでもEntityも再構築が出来ればなんでもok
// EBean
public class EBeanUserRepository implements UserRepository {
@Override
public void save(User user) {
UserId id = user.getId();
models.User userData = Optional
.onNullable(models.User.find.byId(id.getValue()))
.orElseGet(() -> createNew(id, user.getRole()));
userData.setName(user.getName().getValue());
models.User.db().save(userData);
}
}
7. Entities
- 注文の処理やカートに入れる処理
public class User {
private UserId id;
private UserName name;
private UserRole role;
public User(UserId id, UserName name, UserRole role) {
this.id = id;
this.name = name;
this.role = role;
}
public UserId getId() {
return id;
}
public UserName getName() {
return name;
}
public UserRole getRole() {
return role;
}
public void changeName(UserName name) {
this.name = name;
}
}
public class UserName() {
private String value;
public UserName(String value) {
if (value.length() < 3>) throw new RuntimeException();
if (value.length() > 10) throw new RuntimeException();
this.value = value;
}
public String getValue() {
return value;
}
}
8. Output Data
public class UserAddOutputData implements OutputData {
private String createdId;
public UserAddOutputDate(String createId) {
this.createdId = createId;
}
public String getCreatedId() {
return createdId;
}
}
9. Output Boundary
public interface UserAddPresenter {
public void output(UserAddOutputData);
}
10. Presenter
public class ConsoleUserAddPresenter implements UserAddPresenter {
private ConsoleView = new ConsoleView();
public void output(UserAddOutputData outputData) {
String userUuid = outputData.getCreatedId();
ConsoleViewModel viewModel = new ConsoleViewModel(userUuid);
consoleView.showCreatedUserId(viewModel);
}
}
11. View Model
- 実際にデータを出力するのではなく、データの変換をしてあげる