Бизнес логика в доменных объектах

Я кодирую систему ленты / достижений для веб-сайта, и мне нужно написать логику для каждой ленты в моей системе. Например, вы можете заработать ленту, если будете в числе первых 2000 человек, зарегистрировавшихся на сайте, или после 1000 постов на форуме. Идея очень похожа на значки stackru, правда.

Итак, каждая лента, очевидно, находится в базе данных, но им также нужно немного логики, чтобы определить, когда пользователь заработал ленту.

По тому, как я это кодировал, Ribbon это простой интерфейс:

public interface Ribbon {
    public void setId(int id);
    public int getId();
    public String getTitle();
    public void setTitle(String title);
    public boolean isEarned(User user);
}

RibbonJpa абстрактный класс, который реализует Ribbon интерфейс, избегая определения isEarned() метод:

@Entity
@Table(name = "ribbon")
@Inheritance(strategy = InheritanceType.SINGLE_TABLE)
@DiscriminatorColumn(name = "ribbon_type")
public abstract class RibbonJpa implements Ribbon {
    @Id
    @Column(name = "id", nullable = false)
    int id;

    @Column(name = "title", nullable = false)
    private String title;

    @Override
    public int getId() {
        return id;
    }

    @Override
    public void setId(int id) {
        this.id= id;
    }

    @Override
    public String getTitle() {
        return title;
    }

    @Override
    public void setTitle(String title) {
        this.title = title;
    }
}

Вы можете видеть, что я определяю стратегию наследования как SINGLE_TABLE (так как я должен кодировать как 50 лент, и мне не нужны дополнительные столбцы для любой из них).

Теперь конкретная лента будет реализована так:

@Entity
public class FirstUsersRibbon extends RibbonJpa implements Ribbon {
    public FirstUsersRibbon() {
        super.setId(1);
        super.setTitle("First 2,000 users registered to the website");
    }

    @Override
    public boolean isEarned(User user) {
        // My logic to check whether the specified user has won the award
    }
}

Этот код работает нормально, таблицы создаются в базе данных так, как я ожидаю (я использую генерацию DDL в своей локальной среде).

Дело в том, что неправильно кодировать бизнес-логику в доменном объекте. Это хорошая практика? Можете ли вы предложить лучшее решение? Кроме того, я не могу Autowire каких-либо DAO в сущности (FirstUsersRibbon) и мне они нужны в бизнес-логике (в этом случае мне нужен DAO, чтобы проверить, входит ли пользователь в первые 2000 пользователей, зарегистрированных на веб-сайте).

Любая помощь очень ценится.

Спасибо!

2 ответа

Решение

Дело в том, что неправильно кодировать бизнес-логику в доменном объекте.

Многие скажут, что верно обратное: это анти-паттерн (модель анемичной области) иметь бизнес-логику где-либо еще. См. Домен-управляемый дизайн для получения дополнительной информации.

Тогда вы можете спросить, для чего предназначен средний уровень традиционной 3-уровневой архитектуры. Он предоставляет сервисный уровень для приложения. Смотрите мой связанный вопрос " Что такое EJB?"

Кроме того, я не могу автоматически подключать какие-либо DAO в сущности

Если вы используете Spring и Hibernate, взгляните на http://jblewitt.com/blog/?p=129: это дает хорошее описание аналогичной проблемы с различными решениями.

Если вы ищете богатую модель предметной области в том виде, в каком вы ее описали, то было бы неплохо создать экземпляр объекта домена через Spring и, следовательно, иметь возможность внедрять DAO в объекты вашего домена.

Другие вопросы по тегам