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.

Kliknij, aby dodać treść...

Pomoc 1.18.8

Typografia

Edytor obsługuje składnie Markdown, w której pojedynczy akcent *kursywa* oraz _kursywa_ to pochylenie. Z kolei podwójny akcent **pogrubienie** oraz __pogrubienie__ to pogrubienie. Dodanie znaczników ~~strike~~ to przekreślenie.

Możesz dodać formatowanie komendami , , oraz .

Ponieważ dekoracja podkreślenia jest przeznaczona na linki, markdown nie zawiera specjalnej składni dla podkreślenia. Dlatego by dodać podkreślenie, użyj <u>underline</u>.

Komendy formatujące reagują na skróty klawiszowe: Ctrl+B, Ctrl+I, Ctrl+U oraz Ctrl+S.

Linki

By dodać link w edytorze użyj komendy lub użyj składni [title](link). URL umieszczony w linku lub nawet URL umieszczony bezpośrednio w tekście będzie aktywny i klikalny.

Jeżeli chcesz, możesz samodzielnie dodać link: <a href="link">title</a>.

Wewnętrzne odnośniki

Możesz umieścić odnośnik do wewnętrznej podstrony, używając następującej składni: [[Delphi/Kompendium]] lub [[Delphi/Kompendium|kliknij, aby przejść do kompendium]]. Odnośniki mogą prowadzić do Forum 4programmers.net lub np. do Kompendium.

Wspomnienia użytkowników

By wspomnieć użytkownika forum, wpisz w formularzu znak @. Zobaczysz okienko samouzupełniające nazwy użytkowników. Samouzupełnienie dobierze odpowiedni format wspomnienia, zależnie od tego czy w nazwie użytkownika znajduje się spacja.

Znaczniki HTML

Dozwolone jest używanie niektórych znaczników HTML: <a>, <b>, <i>, <kbd>, <del>, <strong>, <dfn>, <pre>, <blockquote>, <hr/>, <sub>, <sup> oraz <img/>.

Skróty klawiszowe

Dodaj kombinację klawiszy komendą notacji klawiszy lub skrótem klawiszowym Alt+K.

Reprezentuj kombinacje klawiszowe używając taga <kbd>. Oddziel od siebie klawisze znakiem plus, np <kbd>Alt+Tab</kbd>.

Indeks górny oraz dolny

Przykład: wpisując H<sub>2</sub>O i m<sup>2</sup> otrzymasz: H2O i m2.

Składnia Tex

By precyzyjnie wyrazić działanie matematyczne, użyj składni Tex.

<tex>arcctg(x) = argtan(\frac{1}{x}) = arcsin(\frac{1}{\sqrt{1+x^2}})</tex>

Kod źródłowy

Krótkie fragmenty kodu

Wszelkie jednolinijkowe instrukcje języka programowania powinny być zawarte pomiędzy obróconymi apostrofami: `kod instrukcji` lub ``console.log(`string`);``.

Kod wielolinijkowy

Dodaj fragment kodu komendą . Fragmenty kodu zajmujące całą lub więcej linijek powinny być umieszczone w wielolinijkowym fragmencie kodu. Znaczniki ``` lub ~~~ umożliwiają kolorowanie różnych języków programowania. Możemy nadać nazwę języka programowania używając auto-uzupełnienia, kod został pokolorowany używając konkretnych ustawień kolorowania składni:

```javascript
document.write('Hello World');
```

Możesz zaznaczyć również już wklejony kod w edytorze, i użyć komendy  by zamienić go w kod. Użyj kombinacji Ctrl+`, by dodać fragment kodu bez oznaczników języka.

Tabelki

Dodaj przykładową tabelkę używając komendy . Przykładowa tabelka składa się z dwóch kolumn, nagłówka i jednego wiersza.

Wygeneruj tabelkę na podstawie szablonu. Oddziel komórki separatorem ; lub |, a następnie zaznacz szablonu.

nazwisko;dziedzina;odkrycie
Pitagoras;mathematics;Pythagorean Theorem
Albert Einstein;physics;General Relativity
Marie Curie, Pierre Curie;chemistry;Radium, Polonium

Użyj komendy by zamienić zaznaczony szablon na tabelkę Markdown.

Lista uporządkowana i nieuporządkowana

Możliwe jest tworzenie listy numerowanych oraz wypunktowanych. Wystarczy, że pierwszym znakiem linii będzie * lub - dla listy nieuporządkowanej oraz 1. dla listy uporządkowanej.

Użyj komendy by dodać listę uporządkowaną.

1. Lista numerowana
2. Lista numerowana

Użyj komendy by dodać listę nieuporządkowaną.

* Lista wypunktowana
* Lista wypunktowana
** Lista wypunktowana (drugi poziom)

Składnia Markdown

Edytor obsługuje składnię Markdown, która składa się ze znaków specjalnych. Dostępne komendy, jak formatowanie , dodanie tabelki lub fragmentu kodu są w pewnym sensie świadome otaczającej jej składni, i postarają się unikać uszkodzenia jej.

Dla przykładu, używając tylko dostępnych komend, nie możemy dodać formatowania pogrubienia do kodu wielolinijkowego, albo dodać listy do tabelki - mogłoby to doprowadzić do uszkodzenia składni.

W pewnych odosobnionych przypadkach brak nowej linii przed elementami markdown również mógłby uszkodzić składnie, dlatego edytor dodaje brakujące nowe linie. Dla przykładu, dodanie formatowania pochylenia zaraz po tabelce, mogłoby zostać błędne zinterpretowane, więc edytor doda oddzielającą nową linię pomiędzy tabelką, a pochyleniem.

Skróty klawiszowe

Skróty formatujące, kiedy w edytorze znajduje się pojedynczy kursor, wstawiają sformatowany tekst przykładowy. Jeśli w edytorze znajduje się zaznaczenie (słowo, linijka, paragraf), wtedy zaznaczenie zostaje sformatowane.

  • Ctrl+B - dodaj pogrubienie lub pogrub zaznaczenie
  • Ctrl+I - dodaj pochylenie lub pochyl zaznaczenie
  • Ctrl+U - dodaj podkreślenie lub podkreśl zaznaczenie
  • Ctrl+S - dodaj przekreślenie lub przekreśl zaznaczenie

Notacja Klawiszy

  • Alt+K - dodaj notację klawiszy

Fragment kodu bez oznacznika

  • Alt+C - dodaj pusty fragment kodu

Skróty operujące na kodzie i linijkach:

  • Alt+L - zaznaczenie całej linii
  • Alt+, Alt+ - przeniesienie linijki w której znajduje się kursor w górę/dół.
  • Tab/⌘+] - dodaj wcięcie (wcięcie w prawo)
  • Shit+Tab/⌘+[ - usunięcie wcięcia (wycięcie w lewo)

Dodawanie postów:

  • Ctrl+Enter - dodaj post
  • ⌘+Enter - dodaj post (MacOS)