ValueObject equality i walidacja w DDD

ValueObject equality i walidacja w DDD
Aenyatia
  • Rejestracja:prawie 7 lat
  • Ostatnio:ponad 3 lata
  • Postów:35
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.

Kopiuj
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;
	}
}
Kopiuj
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?
Kopiuj
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();
	}
}

"Simplicity is the Ultimate Sophistication"
edytowany 1x, ostatnio: Aenyatia
Aventus
  • Rejestracja:około 9 lat
  • Ostatnio:ponad 2 lata
  • Lokalizacja:UK
  • Postów:2235
0

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


Na każdy złożony problem istnieje rozwiązanie które jest proste, szybkie i błędne.
._.
  • Rejestracja:prawie 7 lat
  • Ostatnio:ponad 6 lat
  • Postów:250
0

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

edytowany 1x, ostatnio: ._.
Zobacz pozostały 1 komentarz
._.
Chodzi o wzmocnienie "w tej postaci". Mnie tam pasu jak jest ale polonistą nie jestem.
john_klamka
słowo "bynajmniej" nie ma takiego znaczenia
Patryk27
@john_klamka: podwójne zaprzeczenie występuje w języku polskim, więc IMO całość jest ok - to nie jest żaden VO, nie w tej postaci -> to nie jest żaden VO, bynajmniej (nie) w tej postaci.
Miang
ale fajnie by było jakby polszczyznę walidować jak kod podczas kompilacji
._.
Jak to nie.? PWN -> "Bynajmniej: partykuła wzmacniająca przeczenie zawarte w wypowiedzi" Może "To nie jest, żaden ValueObject bynajmniej, nie w tej postaci." było by bardzie właściwe.
Aenyatia
  • Rejestracja:prawie 7 lat
  • Ostatnio:ponad 3 lata
  • Postów:35
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.


"Simplicity is the Ultimate Sophistication"
._.
  • Rejestracja:prawie 7 lat
  • Ostatnio:ponad 6 lat
  • Postów:250
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ę.?

Aenyatia
Nigdy się nie podszywałem pod kobietę. Czuję się spełniony jako mężczyzna, po prostu piszę z konta siostry bo nie widzę powodów zakładania kolejnego konta i pamiętania kolejnego hasła.
._.
  • Rejestracja:prawie 7 lat
  • Ostatnio:ponad 6 lat
  • Postów:250
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.

Aenyatia
  • Rejestracja:prawie 7 lat
  • Ostatnio:ponad 3 lata
  • Postów:35
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.


"Simplicity is the Ultimate Sophistication"
._.
  • Rejestracja:prawie 7 lat
  • Ostatnio:ponad 6 lat
  • Postów:250
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.

Zarejestruj się i dołącz do największej społeczności programistów w Polsce.

Otrzymaj wsparcie, dziel się wiedzą i rozwijaj swoje umiejętności z najlepszymi.