我正在为Web应用程序创建逻辑来管理用户的同意。
数据库中保留的模型类将具有多个字段,根据用户请求,其中只有一组将被更改。例如班级将有10个字段,并有各种同意,但用户只愿意更改其中2个。为了避免编写大量if-else链,我设计了此类,以利用多态性为我完成工作,但是在某种程度上,这种设计对我来说是有缺陷的。你能告诉我这样做是否合适吗?
问题:仅从类中的大量字段中更改字段子集的值。
为简单起见,我删除了getter / setters方法和一些字段。 更改同意的主要逻辑:
public class GdprServiceImpl implements GdprService {
private final ConsentRepository consentRepository;
@Autowired
public GdprServiceImpl(ConsentRepository consentRepository) {
this.consentRepository = consentRepository;
}
@Override
public void changeConsent(User user, List<ConsentDto> consents) {
Optional<Consent> optionalConsent = consentRepository.findByUser(user);
if(optionalConsent.isPresent()) {
Consent consent = optionalConsent.get();
for(ConsentDto consentDto : consents) {
consentDto.apply(consent);
}
consentRepository.save(consent);
}
else {
Consent consent = new Consent();
consent.setUser(user);
for(ConsentDto consentDto : consents) {
consentDto.apply(consent);
}
consentRepository.save(consent);
}
}
模型类:
public class Consent {
private Boolean messageConsent;
private Boolean recordConsent;
/*CONSTRUCTOR, OTHER METHODS AND FIELDS OMITTED*/
}
将更改同意类中的一组字段的类:
public abstract class ConsentDto {
public abstract void apply(Consent consent);
}
public class RecordConsentDto extends ConsentDto {
private boolean consentValue;
public RecordConsentDto(boolean consentValue) {
this.consentValue = consentValue;
}
@Override
public void apply(Consent consent) {
consent.setRecordConsent(consentValue);
}
}
public class MessageConsentDto extends ConsentDto {
private boolean consentValue;
public MessageConsentDto(boolean consentValue) {
this.consentValue = consentValue;
}
@Override
public void apply(Consent consent) {
consent.setMessageConsent(this.consentValue);
}
}
答案 0 :(得分:2)
您对带有“气味”的设计是正确的。
这是因为数据库设计未标准化。
在一条记录中列出同意列表是一种指示。虽然从技术上讲是允许的,但是经典的RDBMS设计要求将数组表示为表之间的一对多或多对多关系。当然,在对象模型中也是如此。
完全规范化的解决方案将具有一个accept_catalog表以及与用户的多对多关系:
table consent_catalog {
int id // PK
String name
}
目录充当“同意枚举”,每种同意类型(记录,消息等)都有一行
table user_consents {
int user_id references users(id)
int consent_id references consent_catalog(id)
}
此表仅包含用户接受的行。没有“假”同意。这种设计开辟了新的可能性,例如知道哪些用户具有特定的同意或共同同意。
答案 1 :(得分:1)
这种设计感觉有点过分。在一天结束时,您总是在调用consent.setMessageConsent()
或类似的名称,它包含一个枚举字段和一个实现ConsumerDto
的类(实际上是一个Consumer
)。通常,DTO不应实现业务逻辑,但人们可能会说apply
方法是一种。
拥有UserConsent
个字段的Boolean
POJO确实更清洁。唯一的例外是触发一个同意应触发另一个同意,但您的示例尚不清楚。
我只有两美分。我更希望看到传递的是贫乏的POJO或DDD的聚集根,这些根用于管理同意的用户,但两者之间却没有。