Бизнес логика в конструкторе - C # / Linq to Sql - PullRequest
0 голосов
/ 12 марта 2009

Я расширяю (не уверен, что это правильное слово здесь) частичный класс Cart, созданный в модели базы данных Linq to SQL.

Бизнес-логика заключается в том, что на одного покупателя может быть только одна корзина. Если у покупателя нет корзины, ее следует создать; если у покупателя есть корзина, она должна быть возвращена.

Вот что я делаю:

public partial class Cart
{
    //the rest of the Cart class is in the .dbml file created by L2S
    public Cart(int userId)
    {
        Cart c = GetCurrentCart(userId);
        this.CartId = c.CartId ;
        this.UserId = c.UserId;
    }

    public Cart GetCurrentCart(int userId)
    {
        Cart currentCart = new Cart();

        // if cart exists - get it from DB
        //if not - create it, save in DB, and get if right out
        //all of this is done with Linq to SQL

        return currentCart;
    }
}

Вызов метода из конструктора просто не выглядит правильным. Правильно ли я применяю бизнес-логику?

Ответы [ 2 ]

8 голосов
/ 12 марта 2009

Я бы спросил, почему класс "Корзина" такой умный. С точки зрения доменного дизайна, это звучит так, как будто пользователь «владеет» корзиной. Так почему бы не что-то вроде:

var user = // Load a user
var cart = user.Cart;

В этом случае получатель корзины может лениво загрузить / инициализировать корзину.

5 голосов
/ 12 марта 2009

Я согласен с Полом Стовеллом, похоже, пользователь должен владеть корзиной. Но, во всяком случае, к тому времени, когда ваш конструктор вызывается, у вас уже есть новый экземпляр Cart. C # не позволяет вам изменять ссылку, возвращаемую конструктором, поэтому вместо того, чтобы клиенты класса Cart, использующие конструктор, должны вызывать статический метод фабрики (у меня нет опыта работы с Linq to SQL, поэтому это может не сработать) непосредственно).

Ваш метод GetCurrentCart почти такой; вам просто нужно пометить его как статическое. Кроме того, вы должны сделать так, чтобы конструктор Cart отвечал только за создание новой корзины, и сделать ее частной, чтобы клиенты были вынуждены использовать GetCurrentCart. Реализация может выглядеть примерно так:

public partial class Cart
{
        // Make a new cart
        private Cart(int userId, int cartId)
        {
            this.CartId = userId;
            this.UserId = cartId;
        }

        private static Dictionary<int, Cart> CurrentCarts = new Dictionary<int, Cart>();

        public static Cart GetCurrentCart(int userId)
        {
            // TODO: Use a proper caching mechanism that will at least
            //       remove old carts from the dictionary.
            Cart cart;
            if (CurrentCarts.TryGetValue(userId, out cart))
            {
                return cart;
            }

            cart = /* try get cart from DB */;
            if (cart == null)
            {
                // Make a new cart
                cart = new Cart(userId, GenerateCartId());
            }

            CurrentCarts[userId] = cart;

            return cart;
        }
}
...