Always-Valid Domain Model
Vladimir Khorikov

> Valid

Valid
emailAddress使
public class Member {
String emailAddress;
}

public class RegisterMemberUseCase {
private SaveMemberPort saverMemberPort;
void reister(RegisterMemberCommand command) {
//
if (!command.getEmailAddress().matches("^\\S+@\\S+\\.\\S+$")) {
throw new IllegalArgumentException();
}
Member member = new Member(command.getEmailAddress());
saveMemberPort.save(member);
}
}

Member

class Member {
String emailAddress;
public boolean isValid() {
return emailAddress.matches("^\\S+@\\S+\\.\\S+$");
}
}

isValid

@Getter
public class Member {
String emailAddress;
public Member(String emailAddress) {
if (!emailAddress.matches("^\\S+@\\S+\\.\\S+$")) {
throws new IllegalArgumentException();
}
this.emailAddress = emailAddress;
}
}

Always-Valid
EEemailVerifiedVerifyEmailServiceOK

@Getter
public class Member {
String emailAddress;
boolean emailVerified;
}
public interface VerifyEmailService {
boolean verify(String emailAddress);
}
public class VerifyEmailUseCase {
private VerifyEmailService verifyEmailService;
private SaveMemberPort saveMemberPort;
public void verify(VerifyEmailCommand command) {
if (verifyEmailService.verify(command.getEmailAddress())) {
Member member = new Member(command.getEmailAddress(), true);
saveMemberPort.save(member);
} else {
throw new FailToVerifyEmailException();
}
}
}

EEVerifyVerifyEONMember

E(UnverifiedEmailAddress)E(VerifiedEmailAddress)2EEVerifyEE

@Getter
public abstract class EmailAddress {
String value;
}
public class VerifiedEmailAddress extends EmailAddress {
VerifiedEmailAddress(String value) {
super(value);
}
}
public class UnverifiedEmailAddress extends EmailAddress {
public UnverifiedEmailAddress(String value) {
super(value);
}
}
public class Member {
EmailAddress emailAddress;
}
public interface VerifyEmailService {
VerifiedEmailAddress verify(UnverifiedEmailAddress emailAddress);
}
public interface SendNotificationService {
void send(VerifiedEmailAddress emailAddress);
}

Valid
(Design with types)