ОО дизайн - этот дизайн несовершенен? - PullRequest
0 голосов
/ 19 ноября 2018

Я создаю логику для веб-приложения для управления согласиями пользователя.

Класс модели, который сохраняется в БД, будет иметь несколько полей, из которых только набор будет изменен по запросу пользователя. Например В классе будет 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*/
}

Классы, которые будут изменять набор полей из класса Consent:

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);
    }
}

Ответы [ 2 ]

0 голосов
/ 19 ноября 2018

Вы правы в том, что дизайн имеет "запах".
Это потому, что дизайн БД не нормализован.
наличие списка согласий в одной записи является показателем.хотя технически это разрешено, классический дизайн РСУБД диктует, что массивы должны быть представлены как отношения «один ко многим» или «многие ко многим» между таблицами.Конечно, то же самое в объектной модели.

Полностью нормализованное решение будет иметь таблицу согласия_каталога и отношение «многие ко многим» для пользователей:

table consent_catalog {
  int id // PK
  String name
}

Каталог действует как «согласие перечисления»", имеющий одну строку для каждого типа согласия (запись, сообщение и т. д.)

table user_consents {
  int user_id references users(id)
  int consent_id references consent_catalog(id)
}

В этой таблице есть строки только для согласий, принятых пользователем.нет "ложных" согласий.Этот дизайн открывает новые возможности, такие как знание того, какие пользователи имеют конкретное согласие или несколько общих согласий.

0 голосов
/ 19 ноября 2018

Этот дизайн кажется излишним.В конце дня вы всегда вызываете consent.setMessageConsent() или подобное, оно заключено в поле enum и класс, реализующий ConsumerDto (что на самом деле Consumer).Как правило, DTO не должен реализовывать бизнес-логику, но можно утверждать, что метод apply равен единице.

Было бы действительно лучше иметь UserConsent POJO с полями Boolean.Исключение составляет случай, когда инициирование одного согласия должно вызвать другое, но это не ясно из вашего примера.

Только мои два цента.Я бы предпочел, чтобы анемичный POJO проходил вокруг, или агрегированный корень DDD для пользователя, который управляет согласием, но не между ними.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...