Skip to content

Commit

Permalink
hi-level-api, data-modelling and more update
Browse files Browse the repository at this point in the history
  • Loading branch information
googley42 committed Nov 30, 2024
1 parent 1c7fdc5 commit 3496d03
Show file tree
Hide file tree
Showing 5 changed files with 72 additions and 3 deletions.
2 changes: 1 addition & 1 deletion docs/concepts/high-level-api.md
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@ id: high-level-api
title: "High Level API"
---

The high level APi relies on two mechanisms to provide type safety and reduce boilerplate code:
The high level API relies on two mechanisms to provide type safety and reduce boilerplate code:

1. Automatic ZIO Schema derivation for case classes
2. Semi automatic generation of `ProjectionExpression`'s for case classes and sealed traits
Expand Down
53 changes: 53 additions & 0 deletions docs/guides/data-modelling.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,53 @@
---
id: data-modelling
title: "Data Modelling"
---

The High Level API relies heavily on ZIO Schema and inherits some of it's limitations, namely:

- A maximum of **22** fields per case class
- Deep Object Oriented hierarchies with abstract classes/fields are not supported - only hierarchies one level deep are supported

At first glace these seem limitations seem quite restrictive, however the next sections describe how these can be overcome.

## A maximum of **22** fields per case class
The high level API uses the Reified Optics feature of ZIO Schema to generate optics for case classes. This feature has a limitation of 22 fields per case class.

This limitation is something to be aware of when designing your models. In practice however this limitation can be overcome by using nested case classes and in the case of deeply nested hierarchies, by using product and sum types (see section below).

## Deep OO Style hierarchies are not supported - modelling data using Product and Sum Types
Deep Object Oriented like hierarchies with abstract classes/fields are not supported - only hierarchies one level deep are supported - again this is a limitation of ZIO Schema - however these limitations can be overcome by using product and types.


```scala
object OopStyle {
// ensure that all concrete classes have id field
sealed trait Invoice {
def id: Int
}
// (1) Intermediate abstraction with abstract fields - not supported by ZIO Schema
sealed trait Billed extends Invoice {
def amount: Double
}
final case class BilledMonthly(id: Int, amount: Double, month: Int) extends Billed
final case class BilledYearly(id: Int, amount: Double, year: Int) extends Billed
final case class PreBilled(id: Int, count: Int) extends Invoice
}

// FP style modelling uses pure data (product and sum types) rather than inheritance hence avoiding classes like (1)
object FPStyle {
sealed trait BilledBody
final case class BilledMonthly(month: Int) extends BilledBody
final case class BilledYearly(year: Int) extends BilledBody

sealed trait InvoiceBody
// (3) extract product refactoring
final case class Billed(amount: Double, billedBody: BilledBody) extends InvoiceBody
final case class PreBilled(count: Int) extends InvoiceBody

// (2) extract product refactoring
final case class Invoice(int: Int, body: InvoiceBody)
}
```

For brevity the above examples do not show the full integration with ZIO Schema - [for a full example see this IT test](https://github.com/zio/zio-dynamodb/blob/series/2.x/dynamodb/src/it/scala/zio/dynamodb/TypeSafeApiAlternateModeling.scala).
17 changes: 16 additions & 1 deletion docs/reference/hi-level-api/crud-operations/update.md
Original file line number Diff line number Diff line change
Expand Up @@ -20,7 +20,22 @@ for {
} yield maybePerson
```

### `put` query combinators
## update expressions

action | description
---|---
`+` | combines update actions eg `Person.name.set(42) + Person.age.set(42)`
`set` | Set an attribute `Person.name.set("John")`
`setIfNotExists` | Set attribute if it does not exists `Person.name.setIfNotExists("John")`
`appendList` | Add supplied list to the end of this list attribute
`prepend` | Prepend an element to a list attribute
`prependList` | Prepend a list to list attribute
`deleteFromSet` | delete all elements that match the supplied set
`add(a: To)` | adds this value as a number attribute if it does not exists, else adds the numeric value to the existing attribute
`addSet` | Adds this set as an attribute if it does not exists, else if it exists it adds the elements of the set
`remove(index: Int)` | remove an element at the specified index
`remove` | Removes this path expression from an item
### `update` query combinators

```scala
<UPDATE_QUERY>
Expand Down
1 change: 1 addition & 0 deletions docs/sidebars.js
Original file line number Diff line number Diff line change
Expand Up @@ -27,6 +27,7 @@ const sidebars = {
items: [
"guides/getting-started",
"guides/cheat-sheet",
"guides/data-modelling",
"guides/codec-customization",
"guides/testing"
]
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -56,7 +56,7 @@ object TypeSafeApiAlternateModeling extends DynamoDBLocalSpec {
isTest: Boolean,
body: ContractBody
) {
def contractType: String =
val contractType: String =
body match {
case ContractBody.Simple(_) => "simple"
case ContractBody.Group(_, GroupBody.Abc(_, _)) => "group:abc"
Expand Down

0 comments on commit 3496d03

Please sign in to comment.