ValueObject equality i walidacja w DDD

0

Czy Value Objects w DDD muszą mieć wszystkie właściwości takie same, żeby to były te same byty? Niżej kod klasy, która definiuje produkt w koszyku klienta i metoda w klasie ShoppingCart.

public class CartProduct : ValueObject
{
	public Guid ProductId { get; protected set; }
	public decimal UnitPrice { get; protected set; }
	public int Quantity { get; protected set; }
	public decimal Tax { get; protected set; } // podatek będzie obliczany za pomocą serwisu domenowego w zależności od produktu i kraju

	protected CartProduct(Guid productId, decimal unitPrice, int quantity)
	{
		ProductId = productId;
		UnitPrice = unitPrice;
		Quantity = quantity;
	}

	public static CartProduct Create(Product product, int quantity)
	{
		if (product == null)
			throw new ArgumentNullException();

		return new CartProduct(product.Id, product.UnitPrice, quantity);
	}

	public void ChangeQuantity(int quantity)
		=> Quantity += quantity;

	protected override IEnumerable<object> GetEqualityComponents()
	{
		yield return ProductId;
		yield return UnitPrice;
		yield return Tax;
	}
}
public void Add(CartProduct cartProduct)
{
	if (cartProduct == null)
		throw new ArgumentNullException();

	if (_cartProducts.Any(p => p == cartProduct))
	{
		var existingProduct = _cartProducts.Single(p => p == cartProduct);
		existingProduct.ChangeQuantity(cartProduct.Quantity);
		return;
	}

	_cartProducts.Add(cartProduct);
}
  1. W klasie CartProduct mam metodę GetEqualityComponents(), która mówi po jakich właściwościach mam porównywać produkty. W moim przypadku porównuję po id, cenie i podatku ale pomijam ilość. Czy taki byt można nazwać ValueObjectem a może powinienem ilość przenieść do koszyka i np. definiować produkty w koszyku jako Dictionary<CartProduct, int>, gdzie int to ilość?
  2. W DDD walidacja powinna być w modelu czy tak jak w CRUD w warstwie aplikacji? Poniżej kawałek kodu, czy dobrze kombinuję? Czy może powinienem dokonać walidacji od razu na productDto w kontrolerze?
public class Code : ValueObject
{
		public string Ean { get; protected set; }

		protected Code(string ean)
		{
			Ean = ean;
		}

		public static Result<Code> Create(string ean)
		{
			IList<Error> errors = new List<Error>();

			if (ean.IsEmpty())
				errors.Add(DomainErrors.EanEmpty);

			// ...

			return !errors.Any() ?
				Result<Code>.Ok(new Code(ean)) :
				Result<Code>.Fail(errors.ToArray());
		}
		
		protected override IEnumerable<object> GetEqualityComponents()
		{
			yield return Ean;
		}
}

public class ProductService
{
	public Result AddProduct(ProductDto dto)
	{
		var eanResult = Code.Create(dto.Ean);
		if (!eanResult.Succeeded)
			return Result.Fail(eanResult.Errors);

		// ...

		var product = new Product(dto.Name, dto.UnitPrice, eanResult.Value);

		// ...

		return Result.Ok();
	}
}
0

Tak, to właśnie definiuje unikalność Value Objects. W przeciwnym razie są to dwa oddzielne byty.

0

To nie jest, żaden ValueObject bynajmniej, nie w tej postaci. Popełniłaś 2 rażące błędy. Przeczytaj książke.

0

Chodzi ci o zmieniającą się właściwość Quantity i metodę która to powoduje? Wiesz byłbym wdzięczny jak byś mógł mi napisać co zrobiłem źle bo to, że są 2 błędy nie pomaga mi w żaden sposób.

1

Tak wartość ma być nie mutowalna, jest to jeden z 3 podstawowych warunków. Widziałaś kiedyś ceny na produktach, które się same zmieniają? Słyszałaś/słyszałeś kiedyś o czymś takim jak "koszykowy produkt"? Przeczytaj rozdział w książce ile to 10 kartek? Poza tym, po co się podszywasz pod kobietę.?

0

Poza tym prawdopodobnie masz złe założenie odnośnie do modelu. Prawdopodobnie w jednym kontekście produkt powinien być wartością a w drugim agregatem.

0

Produkt jest agregatem, a po dodaniu go do koszyka chcę z niego zrobić obiekt wartościowy. Bez metod i masy innych niepotrzebnych w konteście koszyka właściwości.

2

Więc potrzebujesz do tego dwa konteksty. Narysuj mapę kontekstów i pomyśl. Jeśli sklep to domena to może jeden kontekst powinien być "wystawą sklepową" a drugi "zamówieniami". Wtedy produkt nabiera innego znaczenia w zależności od kontekstu. Dzięki temu nie powstają jakieś dziwne twory.

1 użytkowników online, w tym zalogowanych: 0, gości: 1