Предположим, класс MailConfiguration указывает параметры для отправки писем:
public class MailConfiguration {
private AddressesPart addressesPart;
private String subject;
private FilesAttachments filesAttachments;
private String bodyPart;
public MailConfiguration(AddressesPart addressesPart, String subject, FilesAttachments filesAttachements,
String bodyPart) {
Validate.notNull(addressesPart, "addressesPart must not be null");
Validate.notNull(subject, "subject must not be null");
Validate.notNull(filesAttachments, "filesAttachments must not be null");
Validate.notNull(bodyPart, "bodyPart must not be null");
this.addressesPart = addressesPart;
this.subject = subject;
this.filesAttachements = filesAttachements;
this.bodyPart = bodyPart;
}
// ... some useful getters ......
}
Итак, я использую два объекта значений: AddressesPart и FilesAttachment.
Тезисов дваОбъекты значений имеют схожую структуру, поэтому я собираюсь раскрыть здесь только AddressesPart:
public class AddressesPart {
private final String senderAddress;
private final Set recipientToMailAddresses;
private final Set recipientCCMailAdresses;
public AddressesPart(String senderAddress, Set recipientToMailAddresses, Set recipientCCMailAdresses) {
validate(senderAddress, recipientToMailAddresses, recipientCCMailAdresses);
this.senderAddress = senderAddress;
this.recipientToMailAddresses = recipientToMailAddresses;
this.recipientCCMailAdresses = recipientCCMailAdresses;
}
private void validate(String senderAddress, Set recipientToMailAddresses, Set recipientCCMailAdresses) {
AddressValidator addressValidator = new AddressValidator();
addressValidator.validate(senderAddress);
addressValidator.validate(recipientToMailAddresses);
addressValidator.validate(recipientCCMailAdresses);
}
public String getSenderAddress() {
return senderAddress;
}
public Set getRecipientToMailAddresses() {
return recipientToMailAddresses;
}
public Set getRecipientCCMailAdresses() {
return recipientCCMailAdresses;
}
}
и связанный валидатор: AddressValidator
public class AddressValidator {
private static final String EMAIL_PATTERN
= "^[_A-Za-z0-9-]+(\\.[_A-Za-z0-9-]+)*@[A-Za-z0-9]+(\\.[A-Za-z0-9]+)*(\\.[A-Za-z]{2,})$";
public void validate(String address) {
validate(Collections.singleton(address));
}
public void validate(Set addresses) {
Validate.notNull(addresses, "List of mail addresses must not be null");
for (Iterator it = addresses.iterator(); it.hasNext(); ) {
String address = (String) it.next();
Validate.isTrue(address != null && isAddressWellFormed(address), "Invalid Mail address " + address);
}
}
private boolean isAddressWellFormed(String address) {
Pattern emailPattern = Pattern.compile(EMAIL_PATTERN);
Matcher matcher = emailPattern.matcher(address);
return matcher.matches();
}
}
Таким образом, у меня естьдва вопроса:
1) Если по каким-то причинам позже мы захотим по-разному проверить адрес электронной почты (например, включить / исключить некоторые псевдонимы, соответствующие существующему mailingList), я должен представить вид IValidator какпараметр конструктора?как следующее, а не конкретная зависимость (как я сделал):
public AddressValidator(IValidator myValidator) {
this.validator = myValidator;
}
Действительно, это будет соответствовать принципу D принципа SOLID: Внедрение зависимостей.
Однако, если мы будем следовать этомулогично, будет ли большинство объектов Values иметь абстрактный валидатор, или большую часть времени это просто излишество (подумаете о YAGNI?)?
2) Я читал в некоторых статьях, чем в отношении DDD, все проверки должны присутствовать и присутствовать только в Aggregate Root, в данном случае это означает: MailConfiguration.
Прав ли я, еслиЯ считаю, что неизменяемые объекты никогда не должны находиться в неклейком состоянии?Таким образом, будет ли проверка в конструкторе, как я сделал, предпочтительнее в соответствующей сущности (и, таким образом, избегать агрегирования, чтобы беспокоиться о проверке его «потомков»?