제 질문은 DDD 집계에 도메인 또는 InfrastructureServices를 주입하기 위해 실제로 수행하는 작업에 관한 것입니다. 난 일반 DomainObjects에서 DependencyInjection을 허용하는 것은 나쁜 생각인데, 내 경험으로 볼 때 뾰루지 개발자는 그걸로 불쾌한 일을하기를 권합니다. 그러나 Domainobjects의 DependencyInjection이 이해할 수있는 예외적 인 경우가 특히 있습니다. 특히 가독성과 단순성에 도움이되는 경우에는 특히 그렇습니다. 제 경우에는 aggregate
의 root
중 하나 인 새로운 Ids
을 만드는 방법에 대한 문제를 해결하려고합니다.DDD 집계 및 엔티티의 InversionOfControl (Dependency Injection)
목록이 Address
인 집계를 합계 루트로 갖는 UserAddresses
집계가 있다고 가정합니다. 다음과 같이 단순화
public AddressId changeAddress(AddressId addressId, AddressChangeDto dto) {
Address address = nullableAddress(addressId);
if (address == null) {
// Doesn't matter for this question
} else if (address.hasChanged(dto)) {
address = changeAddress(address, dto);
}
}
및 개인 changeAddress(Address address, AddressChangeDto dto)
방법 :
private Address changeAddress(Address address, AddressChangeDto dto) {
if (!addressCopyNeeded(address)) {
address.change(dto);
return address;
}
// Address is both Shipping- & BillingAddress, hence it must be copied to 2 separate
// entities.
Address copiedAddress = address.copy(new AddressId()); // <-- New AddressId created
...
}
지금 나는 AddressIdFactory
DomainService
에서 생성되는 AddressId
생성을 리팩토링 할의 더 우리가 집합 적 방법 changeAddress(AddressId addressId, AddressChangeDto dto)
을 가정 해 봅시다 기반 도메인에있는 MongoDbRepository를 기반으로하는 내 DomainModel에 머물면서 MongoDb에서 성능이 최적화 된 ObjectId
을 만들었습니다. 긴 UUID보다 선호합니다. 그것은 분명히에 그 방법을 고객에게 혼란을하기 때문에 정말, 전혀 그 디자인 좋아하지 않는다, 그러나
public AddressId changeAddress(AddressId addressId, AddressChangeDto dto, AddressIdFactory idFactory) {
Address address = nullableAddress(addressId);
if (address == null) {
// Doesn't matter for this question
} else if (address.hasChanged(dto)) {
address = changeAddress(address, dto, idFactory);
}
}
private Address changeAddress(Address address, AddressChangeDto dto, AddressIdFactory idFactory) {
if (!addressCopyNeeded(address)) {
address.change(dto);
return address;
}
// Address is both Shipping- & BillingAddress, hence it must be copied to 2 separate
// entities.
Address copiedAddress = address.copy(idFactory.nextAddressId());
...
}
:
하나는 형식 매개 변수 같은으로 그 의존성을 추가하여 그것을 쉽게 해결할 수 첫 번째 광경 : "기존 주소를 변경하려면 왜 AddressIdFactory
을 전달해야합니까?" 클라이언트는 없습니다. 은 내부적으로 진행되고있는 작업과 특정 별자리에 새 주소를 만들어야 할 가능성이 있음을 알고 할 필요가 없습니다. 이것은 또한 다음 단락으로 이어질 수 있습니다. 우리는 또한 여러분이 말할 수있는 전체 메소드를 리팩터링 할 수 있지만, 이는 클라이언트가 새로운 AddressId를 전달하거나 메소드 매개 변수로 xyz DomainService를 전달할 책임이있는 디자인으로 이어질 것입니다. 내 생각에 단순히 최적이 아니다.
왜냐하면 나는 예외적 인 경우로서 그 문제에 대한 의존성 주입을 생각하면 "언제"와 "어떻게"라는 논리를 유지하면서 간단하게하기 위해 집계에 새 주소를 만들 수 있을지 생각하고 있습니다. 집계 고객.
질문은 입니다.입니다. 예, 우리는 Spring을 사용하고 있습니다. 전체 집계가 지속되는 Spring Data MongoDb 객체이기 때문에 DomainService를 자동으로 사용할 수 없습니다.이 객체는 런타임 중에 JSON에서 DomainObject를 deserialize합니다. 내가 "다운"집계에 공개 세터에 대해서만이 때문에 물론
@Aggregate
@Document(collection = "useraddresses)
public class UserAddresses extends Entity {
// When reading from MongoDb the object's creation lays in the responsibility of
// Spring Data MongoDb, not Spring, therefore Spring cannot inject the dependency
// at all.
@Autowired
private AddressIdFactory addressIdFactory;
@PersistenceConstructor
public UserAddresses(String id, Map<String, Address> userAddresses) {
setUserAddressesId(new UserAddressesId(id));
if (userAddresses != null) {
this.userAddresses.putAll(userAddresses);
}
}
, 그러나 나는이뿐만 아니라 못생긴, 세터() 또는 뭔가를 호출하여 리포지토리에 수동으로 의존성을 주입 할 수 기술적 인 관심사의 목적.
또 다른 아이디어는 리플렉션을 사용하여 사적인 필드에 직접 종속성을 설정하는 것입니다. 그러나 이것 역시 추악하고 약간의 성능 단점이 있습니다.
귀하의 접근 방법이 궁금합니다.
당신의 대답은 내가 stackoverflow를 좋아하는 이유 중 하나입니다. 나는 이것에 대해 전혀 생각하지 않았고 확실히 PoC 할 것이다, 고마워! –
나는 이것을 poced했다. 나는 그것이 sig 메소드를 확장 할 수있게 해 준 것을 좋아한다. Impl을 사용하고 인터페이스를 단순하게 유지하십시오. 그러나 나는 어댑터가 실제로 인터페이스를 구현해야하며 더 이상 자체적으로 집계를 구현해야한다는 것을 싫어한다. "코드 찾기"의 경우 IDE에서 두 번째 단계를 수행하여 어댑터에서 집계로 이동해야합니다. UserAddressesImpl은 필드 종속성을 주입하기위한 공용 설정자를 제공하지만 두 솔루션 모두 장단점을 구현하는 두 번째 솔루션을 마련했습니다. 두 솔루션 모두 장점과 단점을 모두 지니고 있습니다. –