I wrote it only with momentum! As the title says!
Suddenly, when I listen to stories and watch twitter at study sessions, I feel that there are often entities that use the nouns they find as classes and throw all the data-like things around them into them. I also wrote when I was a beginner w
UserStatus.java
public enum UserStatus {
Applying, //Applying
Using, //in use
Leaved, //Withdrawn
BlackListed, //blacklist
Erased, //Erase
}
(Only) ʻUser`, which has such a state, has been represented by one class!
I think it's common at the stage, "Because it's DDD, create a class called User and write the processing there." I'm sure it wasn't in good shape at first, but I understand that it ended up being a mess while doing analysis or service growth. Unun
User.java
public class User {
private UserId userId;
private UserCourse userCourse;
private UserStatus userStatus;
private ApplyDate applyDate;
private Optional<UseStartDate> useStartDate;
private Optional<LeaveDate> leaveDate;
private Optional<EraseDate> eraseDate;
public User apply(UserCourse userCourse) {
return new User(
new UserId(), userCourse, Applying, new ApplyDate(), Optional.empty(), Optional.empty(), Optional.empty()
);
}
public User useStart() {
if (userStatus != Applying)
throw new RuntimeException("not applying");
return new User(
userId, userCourse, Using, applyDate, Optional.of(new UseStartDate()), leaveDate, eraseDate
);
}
public User courseChange(UserCourse userCourse) {
if (userStatus != Using)
throw new RuntimeException("not using");
return new User(
userId, userCourse, userStatus, applyDate, useStartDate, leaveDate, eraseDate
);
}
public User leave() {
if (userStatus != Using)
throw new RuntimeException("not using");
return new User(
userId, userCourse, Leaved, applyDate, useStartDate, Optional.of(new LeaveDate()), eraseDate
);
}
public User blackListIn() {
if (userStatus != Using)
throw new RuntimeException("not using");
return new User(
userId, userCourse, BlackListed, applyDate, useStartDate, leaveDate, eraseDate
);
}
public User blackListOut() {
if (userStatus != BlackListed)
throw new RuntimeException("not black listed");
return new User(
userId, userCourse, Using, applyDate, useStartDate, leaveDate, eraseDate
);
}
public User erase() {
if (userStatus != BlackListed)
throw new RuntimeException("not black listed");
return new User(
userId, userCourse, Erased, applyDate, useStartDate, leaveDate, Optional.of(new EraseDate())
);
}
}
The code to use is like this
UserService.java
public class UserService {
public void leave(UserId userId) {
User usingUser = userRepository.find(userId);
User leavedUser = usingUser.leave();
userRepository.leave(leavedUser);
billing.stop(leavedUser.getLeaveDate().get());
...
}
}
Uhe ~ spicy ~
The code is long! Even if you compile it, you will get an execution exception! I mean, domain logic is Nani!
** This isn't almost a DTO ~? ** **
I will omit the implementation, but let's divide the class according to the state.
There are two points!
The main benefits!
leavedUser.getLeaveDate (). Get ()
It's easy, but it's super effective, so give it a try!
I used the state in the example, but it depends on the modeling. The use cases and the degree of business impact must be different.
And this split isn't "this is DDD!" But "just a starting point"! This way you can make the model smaller, analyze it, and sort out the logic!
For example, in this example, the billing stop (billing.stop (...)
) is modeled starting with LeavedUser
.
If you take a little care, even if you think you created an entity, it will be just a DTO, so be careful!
By the way, I wrote a similar article about two years ago, if you like it, please. [It feels good to prepare different classes even with the same table values # Case 2-Update the status of one class](https://qiita.com/suzuki-hoge/items/b8eb2fe9fbe551cfede4#%E3%82%B1% E3% 83% BC% E3% 82% B92-% EF% BC% 91% E3% 81% A4% E3% 81% AE% E3% 82% AF% E3% 83% A9% E3% 82% B9% E3 % 81% AE% E7% 8A% B6% E6% 85% 8B% E6% 9B% B4% E6% 96% B0% E3% 82% 92% E3% 81% 99% E3% 82% 8B)
Recommended Posts