Composizione dei domini
Costruisca modelli più grandi
Composizione dei domini è una lezione Scala for Backend Engineering & Functional Programming gratuita su CoddyKit. Questa è la lezione 4 di 4. Puoi leggere la lezione completa qui gratuitamente — poi esercitati direttamente nel browser con un editor di codice integrato e un tutor IA disponibile 24/7. Fa parte del percorso di apprendimento Scala for Backend Engineering & Functional Programming, e i tuoi progressi si sincronizzano tra il web e l'app CoddyKit. Il corso Scala for Backend Engineering & Functional Programming include 4 lezioni in totale.
Costruire modelli più grandi
I domini reali sono assemblati a partire da componenti più piccoli. Comporre i domini significa combinare ADT, newtype e valori validati ben modellati in strutture più grandi, che restano corrette.
- I tipi piccoli e focalizzati si compongono in tipi più grandi.
- Ogni componente mantiene i propri invarianti.
case class Money(cents: Long)
case class Product(name: String, price: Money)
object Main:
def main(args: Array[String]): Unit =
println(Product("Book", Money(1999)))Nidificare i product type
Componete i product type nidificando le case class. Ogni livello aggiunge struttura mantenendo il codice leggibile.
case class Address(city: String, zip: String)
case class Customer(name: String, address: Address)
object Main:
def main(args: Array[String]): Unit =
val c = Customer("Ada", Address("London", "E1"))
println(c.address.city)Comporre con le collection
Usate List, Map e Set per modellare relazioni uno-a-molti all'interno del dominio.
case class Item(name: String, qty: Int)
case class Order(id: Int, items: List[Item])
object Main:
def main(args: Array[String]): Unit =
val order = Order(1, List(Item("pen", 2), Item("ink", 1)))
println(order.items.map(_.qty).sum)Comporre i sum type
Le scelte più grandi combinano quelle più piccole. Una variante di un enum può contenere a sua volta un altro ADT, creando livelli di decisioni.
enum Payment:
case Card(last4: String)
case Cash
enum Checkout:
case Completed(payment: Payment)
case Abandoned
object Main:
def main(args: Array[String]): Unit =
val c: Checkout = Checkout.Completed(Payment.Card("1234"))
println(c)Funzioni che compongono i domini
Le operazioni di dominio sono funzioni pure che trasformano tipi di input in tipi di output. Comporle permette di costruire workflow.
case class Cart(total: Long)
case class Receipt(total: Long, tax: Long)
object Main:
def checkout(c: Cart): Receipt =
Receipt(c.total, (c.total * 0.2).toLong)
def main(args: Array[String]): Unit =
println(checkout(Cart(1000)))Comporre le validazioni
Quando ogni campo viene costruito da un costruttore intelligente, potete comporli con una comprehension for. L'oggetto completo viene creato solo se ogni componente supera la validazione.
object V:
def name(s: String): Option[String] = if s.nonEmpty then Some(s) else None
def age(n: Int): Option[Int] = if n >= 0 then Some(n) else None
case class Person(name: String, age: Int)
object Main:
def make(n: String, a: Int): Option[Person] =
for nm <- V.name(n); ag <- V.age(a) yield Person(nm, ag)
def main(args: Array[String]): Unit =
println(Main.make("Bob", 30))
println(Main.make("", 30))Fare il fold su dati compositi
Aggregate le strutture composte con fold oppure con map più sum. È la forma dei dati a guidare il calcolo.
case class Line(price: Long, qty: Int)
case class Invoice(lines: List[Line])
object Main:
def total(inv: Invoice): Long =
inv.lines.foldLeft(0L)((acc, l) => acc + l.price * l.qty)
def main(args: Array[String]): Unit =
val inv = Invoice(List(Line(100, 2), Line(50, 4)))
println(total(inv))Aggiornare modelli immutabili
Componete le modifiche con copy, che restituisce un nuovo valore sostituendo i campi selezionati. L'originale rimane invariato.
case class Account(id: Int, balance: Long)
object Main:
def deposit(a: Account, amt: Long): Account =
a.copy(balance = a.balance + amt)
def main(args: Array[String]): Unit =
val a = Account(1, 100)
println(deposit(a, 50))Modellare una macchina a stati
Componete sum type e funzioni di transizione per modellare una macchina a stati in cui esistono solo transizioni valide.
enum Light:
case Red, Green, Yellow
object Main:
def next(l: Light): Light = l match
case Light.Red => Light.Green
case Light.Green => Light.Yellow
case Light.Yellow => Light.Red
def main(args: Array[String]): Unit =
println(next(Light.Red))
println(next(Light.Green))Sovrapporre dominio e operazioni
Mantenete puri i tipi di dati e inserite il comportamento nelle funzioni o nei metodi. Un modello composto insieme a un insieme di trasformazioni forma una piccola libreria di dominio.
case class Temp(celsius: Double):
def toF: Double = celsius * 9 / 5 + 32
object Main:
def main(args: Array[String]): Unit =
val t = Temp(25.0)
println(t.toF)Mettere tutto insieme
Un modello completo combina newtype, product type, sum type, collection e costruzione validata. Il risultato è difficile da usare in modo errato e facile da comprendere.
- Costruite prima i tipi piccoli.
- Componeteli in aggregati.
- Esprimete le operazioni come funzioni pure.
case class Sku(value: String)
case class Line(sku: Sku, qty: Int)
case class Basket(lines: List[Line]):
def count: Int = lines.map(_.qty).sum
object Main:
def main(args: Array[String]): Unit =
val b = Basket(List(Line(Sku("A"), 2), Line(Sku("B"), 3)))
println(b.count)Verifica rapida
Verificate la vostra comprensione della composizione dei domini.
Riepilogo
Avete imparato a comporre i domini.
- Nidificate product type e sum type per modellare strutture ricche.
- Usate le collection per le relazioni uno-a-molti.
- Componete le validazioni con le comprehension
for. - Aggiornate i dati in modo immutabile con
copy. - Mantenete puri i dati ed esprimete le operazioni come funzioni.
case class User(id: Int, name: String)
case class Post(author: User, text: String)
object Main:
def main(args: Array[String]): Unit =
val p = Post(User(1, "Ada"), "hello")
println(p.copy(text = "hi"))Domande Frequenti
La lezione «Composizione dei domini» è gratuita?
Sì — il testo completo di «Composizione dei domini» è gratuito qui sul web. Per esercitarvi in modo interattivo (un editor di codice integrato e un tutor IA 24/7) e sbloccare il resto del corso Scala for Backend Engineering & Functional Programming, passa a CoddyKit PRO. Il corso Scala for Backend Engineering & Functional Programming include 4 lezioni in totale.
Cosa imparerò in «Composizione dei domini»?
Costruisca modelli più grandi Eserciti Scala for Backend Engineering & Functional Programming con codice pratico che esegui direttamente nel browser, e un tutor IA 24/7 risponde alle tue domande mentre lavori sulla lezione.
Ho bisogno di esperienza per iniziare Scala for Backend Engineering & Functional Programming?
Non è richiesta alcuna esperienza precedente. Scala for Backend Engineering & Functional Programming su CoddyKit è strutturato per principianti e studenti avanzati, quindi puoi iniziare da qui o dall'inizio e procedere al tuo ritmo. Questa è la lezione 4 di 4.
Quanto tempo richiede la lezione «Composizione dei domini»?
La maggior parte delle lezioni CoddyKit richiede circa 5–10 minuti. Ogni lezione è breve e interattiva, quindi fai progressi costanti e riprendi esattamente da dove hai lasciato su web e app.
Posso scrivere ed eseguire codice in questa lezione Scala for Backend Engineering & Functional Programming?
Sì. Ogni lezione Scala for Backend Engineering & Functional Programming include un editor di codice integrato, quindi scrivi ed esegui codice reale direttamente nel tuo browser e ricevi feedback istantaneo dall'IA — nessuna configurazione locale necessaria.
Tutte le lezioni di questo corso
- Modellazione con gli ADT
- Costruttori intelligenti
- Newtype
- Composizione dei domini