0Pricing
TypeScript Academy · Lekcja

Modelowanie domeny — agregaty, niezmienniki i usługi

Modelowanie agregatów, takich jak Cart, za pomocą brandowanych identyfikatorów oraz wymuszanie niezmienników przez fabryki i usługi

Modelowanie domeny — agregaty, niezmienniki i usługi to bezpłatna lekcja TypeScript Academy na CoddyKit. To lekcja 3 z 3. Możesz przeczytać całą lekcję poniżej za darmo — a potem ćwiczyć ją interaktywnie w przeglądarce z wbudowanym edytorem kodu i tutorem AI dostępnym 24/7. To część ścieżki edukacyjnej TypeScript Academy, a Twój postęp synchronizuje się między webem a aplikacją CoddyKit. Kurs TypeScript Academy zawiera 3 lekcji w sumie.

Wprowadzenie

Cel: Modelowanie agregatu Cart za pomocą brandowanych identyfikatorów i zapewnienie egzekwowania reguł, takich jak qty > 0, w fabrykach i usługach.

  • Brandowane identyfikatory rozróżniają granice encji
  • Fabryki zwracają unie Result
  • Funkcje usługowe unikają nieprawidłowych przejść stanu

Encje i brandy

Brandowane identyfikatory sprawiają, że CartId i ProductId są niekompatybilne, mimo że oba mają typ string. Zapobiega to pomyłkom.

type Brand<Tag extends string, T> = T & { readonly __brand: Tag }

type CartId = Brand<"CartId", string>
type ProductId = Brand<"ProductId", string>

type Result<T> = { ok: true; value: T } | { ok: false; error: string }

const cartId = (s: string): CartId => s as CartId
const productId = (s: string): ProductId => s as ProductId

Agregat i niezmiennik

Fabryki sprawdzają reguły: qty musi być większe niż > 0. Można utworzyć wyłącznie poprawne obiekty Line.

type Money = number & { readonly __brand: "Money" }
const money = (n: number): Money => n as Money

interface Line { productId: ProductId; qty: number; price: Money }
interface Cart { id: CartId; lines: Line[]; total: Money }

function makeLine(productId: ProductId, qty: number, price: Money): Result<Line> {
  if (!Number.isInteger(qty) || qty <= 0) return { ok: false, error: "qty must be > 0" }
  return { ok: true, value: { productId, qty, price } }
}

function makeCart(id: CartId): Cart { return { id, lines: [], total: money(0) } }

Usługa: dodawanie elementu

Funkcje usługowe wykonują bezpieczne przejścia i ponownie obliczają sumy. Jeśli sumy są nieprawidłowe, funkcja zwraca błąd zamiast uszkodzić stan.

function addItem(cart: Cart, line: Line): Result<Cart> {
  const lines = [...cart.lines, line]
  const totalNum = lines.reduce((s, x) => s + (x.qty * (x.price as number)), 0)
  if (!Number.isFinite(totalNum) || totalNum < 0) return { ok: false, error: "invalid total" }
  return { ok: true, value: { ...cart, lines, total: (totalNum as unknown) as Money } }
}

// Usage
const c0 = makeCart(cartId("c1"))
const l = makeLine(productId("p1"), 2, money(10))
const c1 = l.ok ? addItem(c0, l.value) : { ok: false, error: "bad line" }

Mapowanie na granicach systemu

Na granicach systemu (np. w API) należy konwertować dane na DTO i weryfikować je podczas ponownego parsowania. Fabryki zapewniają poprawność danych.

type CartDTO = { id: string; lines: { productId: string; qty: number; price: number }[]; total: number }

function serialize(c: Cart): CartDTO {
  return {
    id: c.id as unknown as string,
    lines: c.lines.map(x => ({ productId: x.productId as unknown as string, qty: x.qty, price: x.price as unknown as number })),
    total: c.total as unknown as number
  }
}

function parse(dto: CartDTO): Result<Cart> {
  const id = cartId(dto.id)
  const lines: Line[] = []
  for (const raw of dto.lines) {
    const l = makeLine(productId(raw.productId), raw.qty, money(raw.price))
    if (!l.ok) return { ok: false, error: l.error }
    lines.push(l.value)
  }
  const totalNum = lines.reduce((s, x) => s + (x.qty * (x.price as number)), 0)
  return { ok: true, value: { id, lines, total: money(totalNum) } }
}

Wskazówki

Najlepsze praktyki:

  • Centralizować walidację w fabrykach.
  • Utrzymywać funkcje usługowe jako czyste i deterministyczne.
  • Wykonywać konwersje brandów wyłącznie na granicach systemu.

Sprawdzenie niezmiennika

Szybkie sprawdzenie: Jak należy egzekwować niezmiennik taki jak qty > 0?

Podsumowanie

Podsumowanie: Brandowane identyfikatory w połączeniu z fabrykami i usługami egzekwują niezmienniki. Nieprawidłowe stany nie mogą zostać utworzone, ponieważ wszystkie punkty wejścia weryfikują dane.

Często zadawane pytania

Czy lekcja „Modelowanie domeny — agregaty, niezmienniki i usługi” jest bezpłatna?

Tak — pełny tekst „Modelowanie domeny — agregaty, niezmienniki i usługi” jest dostępny za darmo tutaj w sieci. Aby ćwiczyć ją interaktywnie (wbudowany edytor kodu i tutor AI dostępny 24/7) i odblokować resztę kursu TypeScript Academy, przejdź na CoddyKit PRO. Kurs TypeScript Academy zawiera 3 lekcji w sumie.

Co nauczysz się w „Modelowanie domeny — agregaty, niezmienniki i usługi”?

Modelowanie agregatów, takich jak Cart, za pomocą brandowanych identyfikatorów oraz wymuszanie niezmienników przez fabryki i usługi Ćwiczysz TypeScript Academy z praktycznym kodem, który uruchamiasz bezpośrednio w przeglądarce, a tutor AI dostępny 24/7 odpowiada na Twoje pytania podczas pracy nad lekcją.

Czy potrzebuję doświadczenia, aby zacząć TypeScript Academy?

Nie wymagamy żadnego doświadczenia. TypeScript Academy w CoddyKit jest strukturyzowany dla początkujących i zaawansowanych użytkowników, więc możesz zacząć tutaj lub od początku i uczyć się w swoim tempie. To lekcja 3 z 3.

Ile czasu zajmuje lekcja „Modelowanie domeny — agregaty, niezmienniki i usługi”?

Większość lekcji CoddyKit trwa około 5–10 minut. Każda lekcja to mały, interaktywny krok, dzięki czemu robisz systematyczne postępy i zawsze wracasz dokładnie do tego samego miejsca — na webie i w aplikacji.

Czy mogę pisać i uruchamiać kod w tej lekcji TypeScript Academy?

Tak. Każda lekcja TypeScript Academy zawiera wbudowany edytor kodu, więc piszesz i uruchamiasz prawdziwy kod bezpośrednio w przeglądarce i od razu otrzymujesz sprzężenie zwrotne od AI — bez konfiguracji na komputerze.

Wszystkie lekcje w tym kursie

  1. Typy branding/opaque zapobiegające pomyłkom jednostek
  2. Identyfikatory tagowane i wzorce modelowania domeny
  3. Modelowanie domeny — agregaty, niezmienniki i usługi
← Powrót do TypeScript Academy