Composição de domínios
Construa modelos maiores
Composição de domínios é uma aula grátis de Scala for Backend Engineering & Functional Programming no CoddyKit. Esta é a aula 4 de 4. Você pode ler a aula completa abaixo gratuitamente — depois pratica ao vivo no navegador com um editor de código integrado e um tutor de IA 24/7. Faz parte do caminho de aprendizado de Scala for Backend Engineering & Functional Programming, e seu progresso é sincronizado entre a web e o app CoddyKit. O curso de Scala for Backend Engineering & Functional Programming inclui 4 aulas no total.
Construindo modelos maiores
Domínios reais são montados a partir de componentes menores. Compor domínios significa combinar ADT, newtypes e valores validados bem modelados em estruturas maiores que continuam corretas.
- Tipos pequenos e focados podem ser combinados em tipos maiores.
- Cada componente mantém suas próprias invariantes.
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)))Aninhando produtos
Componha tipos produto aninhando case classes. Cada nível adiciona estrutura sem perder a legibilidade.
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)Compondo com coleções
Use List, Map e Set para modelar relações de um para muitos dentro do seu domínio.
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)Compondo tipos soma
Escolhas maiores combinam escolhas menores. Uma variante de enum pode conter outro ADT, criando camadas de decisões.
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)Funções que compõem domínios
As operações de domínio são funções puras que recebem tipos de entrada e produzem tipos de saída. Combiná-las permite construir fluxos de trabalho.
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)))Compondo validações
Quando cada campo é construído por um construtor inteligente, componha-os com uma compreensão for. O objeto inteiro só é criado se todas as partes forem validadas.
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))Reduzindo dados compostos
Agregue estruturas compostas com fold ou com map mais sum. A forma dos dados orienta o cálculo.
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))Atualizando modelos imutáveis
Componha alterações com copy, que retorna um novo valor com os campos selecionados substituídos. O original permanece intacto.
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))Modelando uma máquina de estados
Componha tipos soma e funções de transição para modelar uma máquina de estados na qual só existem transições legais.
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))Separando domínio e operações em camadas
Mantenha os tipos de dados puros e coloque o comportamento em funções ou métodos. Um modelo composto com um conjunto de transformações forma uma pequena biblioteca de domínio.
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)Juntando tudo
Um modelo completo combina newtypes, produtos, somas, coleções e construção validada. O resultado é difícil de usar incorretamente e fácil de compreender.
- Comece construindo tipos pequenos.
- Combine-os em agregados.
- Expresse as operações como funções puras.
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ção rápida
Teste sua compreensão da composição de domínios.
Recapitulação
Você aprendeu a compor domínios.
- Aninhe produtos e somas para modelar estruturas ricas.
- Use coleções para relacionamentos de um para muitos.
- Componha validações com compreensões
for. - Atualize de forma imutável com
copy. - Mantenha os dados puros e expresse as operações como funções.
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"))Aprenda Scala com um tutor de IA — grátis
Escreva e execute código real no seu navegador, obtenha ajuda instantânea de um tutor de IA 24/7 e continue de onde parou na web ou no app.
- Cursos
- 39
- Aulas
- 143
Perguntas Frequentes
A aula “Composição de domínios” é grátis?
Sim — o texto completo de “Composição de domínios” é grátis para ler aqui na web. Para praticá-la interativamente (um editor de código integrado e um tutor de IA 24/7) e desbloquear o restante do curso de Scala for Backend Engineering & Functional Programming, atualize para CoddyKit PRO. O curso de Scala for Backend Engineering & Functional Programming inclui 4 aulas no total.
O que vou aprender em “Composição de domínios”?
Construa modelos maiores Você pratica Scala for Backend Engineering & Functional Programming com código prático que executa diretamente no navegador, e um tutor de IA 24/7 responde suas dúvidas enquanto trabalha na aula.
Preciso ter experiência prévia para começar Scala for Backend Engineering & Functional Programming?
Nenhuma experiência prévia é necessária. Scala for Backend Engineering & Functional Programming no CoddyKit é estruturado para alunos iniciantes até avançados, então você pode começar aqui ou desde o início e aprender no seu ritmo. Esta é a aula 4 de 4.
Quanto tempo leva a aula “Composição de domínios”?
A maioria das aulas CoddyKit leva cerca de 5–10 minutos. Cada uma é compacta e interativa, então você faz progresso constante e retoma exatamente de onde parou entre web e app.
Posso escrever e executar código nesta aula de Scala for Backend Engineering & Functional Programming?
Sim. Cada aula de Scala for Backend Engineering & Functional Programming inclui um editor de código integrado, então você escreve e executa código real direto no navegador e recebe feedback de IA instantaneamente — nenhuma configuração local necessária.
Todas as aulas deste curso
- Modelagem com ADTs
- Construtores inteligentes
- Newtypes
- Composição de domínios