Как мне предотвратить повторение бизнес-логики? - PullRequest
0 голосов
/ 26 октября 2009

OK. Итак, вот мой упрощенный сценарий. У нас есть система, которая обрабатывает заказы для ряда клиентов. Мы хотим, чтобы пользователи-сотрудники могли просматривать все заказы, и мы хотим, чтобы пользователь-клиент мог просматривать только те заказы, которые относятся к ним.

При попытке просмотреть определенную запись мы используем следующую функцию в нашем классе OrderSecurity:

Public Function CanViewOrder(order)
    If currentUser.MemberOfStaff() Then
        CanViewOrder = True
    Else
        CanViewOrder = (order.ClientId = currentUser.ClientId)
    End If
End Function

В моменты, когда мы хотим отобразить список заказов пользователю, мы можем выполнить следующую функцию, определенную в классе OrderService

Public Function GetOrders()
    If currentUser.MemberOfStaff() Then
        GetOrders = GetAllOrders()
    Else
        GetOrders = GetAllOrdersForClient(currentUser.ClientId)
    End If
End Function

Это нормально для вышеперечисленного, но не очень хорошо, поскольку правила усложняются. Скажем, например, мы добавляем другой тип пользователя, который представляет менее доверенного сотрудника, который может просматривать заказы только из подмножества клиентов. Затем нам нужно добавить логику в функции CanViewOrder и GetOrders (и, возможно, в классы доступа к данным), что, на мой взгляд, нарушает принцип DRY.

Итак, мой вопрос: я здесь упускаю хитрость - есть ли способ объединить бизнес-логику для разрешения просмотра заказов в одном месте, которое могут использовать обе эти функции?

Или я слишком много волнуюсь, и мне нужно просто встать и иметь логику в двух местах?

(В этом конкретном приложении я использую ASP Classic - не ненавидь игрока, ненавидь игру - но мне было бы интересно узнать, как решить эту проблему на любом языке)

Ответы [ 2 ]

1 голос
/ 27 октября 2009

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

Public Function CanView(user, order)
    (magic)
End Function

Тогда избегайте повторения политики доступа, применив GetOrders(user) в качестве фильтра, применяющего CanView(user, order) к набору заказов.

Пройдя по этому пути, вы также можете раз и навсегда определить другие «запросы», независимо от политики и того, как она может измениться. Например: GetUsersWhoCanView(order), CanViewSameOrders(user1, user2), CanAnybodyView(order), ...

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

1 голос
/ 26 октября 2009

ИМО ты здесь не повторяешься. Бизнес-логика в CanViewOrder отличается от бизнес-логики в GetOrders. Это внешнее сходство, это правда, но эти два правила теоретически могут развиваться по-разному.

...