Java интерфейс для entity/dto или передача метода по ссылке?

Я пытаюсь создать класс валидатор с несколькими простыми правилами проверки. Эти правила могут применяться одинаково к разным типам Hibernate entity (или DTO), и я хотел бы унифицировать этот класс без создания разных реализаций.

Я пытаюсь сделать это с помощью дженериков, но проблема в том, что, хотя каждый тип валидируемого объекта имеет определенный геттер (getCatalog), я не могу вызвать его с помощью дженериков не реализуя общий интерфейс или не расширяя абстрактный класс. Я думаю, что интерфейс для entity / dto в таком случае не является хорошим выбором, хотя может я и не прав и интерфейс типа Cataloged или HasCatalog допустим для таких целей..

Validator class
public class Validator<T> {

public boolean validate(List<T> objects, Function<T, Catalog> catalogGetter) {

    if (CollectionUtils.isEmpty(objects)) {
        return false;
    }
    if (differentCatalogsInLoadExist(objects, catalogGetter)) {
        return false;
    }
    if (catalogForObjectNotExists(objects, catalogGetter)) {
        return false;
    }
    return true;
}

private boolean differentCatalogsInLoadExist(List<T> objects, Function<T, Catalog> catalogGetter) {
    return objects.stream()
            .map(catalogGetter)
            .map(catalog -> catalog.getCatalogCode())
            .distinct()
            .count() > 1;
}

private boolean catalogForObjectNotExists(List<T> objects, Function<T, Catalog> catalogGetter) {
    return objects.stream()
            .map(catalogGetter)
            .findFirst()
            .isEmpty();
}

}


Основная моя цель - избавиться от этого Function<T, Catalog> catalogGetter

Может есть более красивый способ или вариант с интерфейсом тут допустим?
  • Вопрос задан
  • 67 просмотров
Пригласить эксперта
Ответы на вопрос 1
@vabka
Fullstack dev
1. Я бы не стал делать в валидаторе сигнатуру, которая принимает список объектов.
Как минимум из-за того, что ему не нужен весь интерфейс, который даёт List. А как максимум - это просто не красиво.
2. Я бы не стал валидировать объекты, которые лежат в базе (считается, что раз объект попал в базу, то он уже валиден). Так что имеет смысл валидировать только DTO.
3. Вы правы, прокидывать лямбду для геттера в метод - это плохо.
я бы сделал билдер для валидатора, наподобие
// Псевдо-Java
var validator = new ValidatorBuilder<MyDto>()
                                .rule(d -> d.catalogues, catalogues -> catalogues.stream().map(c -> c.code).distinct().count() > 1)
                                // etc
                                .build();
var dto = //как-то получаем экземпляр dto
var dtoValid = validator.validate(dto);

PS:
Вдохновлялся шарповым FluentValidation - можете посмотреть на его API, но я бы не стал пытаться его портировать на Java, тк там много зависимостей от чисто шарповых штук
Ответ написан
Ваш ответ на вопрос

Войдите, чтобы написать ответ

Войти через центр авторизации
Похожие вопросы
МегаФон Нижний Новгород
от 60 000 ₽
от 170 000 до 250 000 ₽
KubRu Москва
от 50 000 до 100 000 ₽
09 апр. 2020, в 01:27
1000 руб./за проект
08 апр. 2020, в 22:52
5000 руб./за проект
08 апр. 2020, в 21:19
10000 руб./за проект