Skip to content

Commit

Permalink
.
Browse files Browse the repository at this point in the history
  • Loading branch information
danjoa committed Nov 25, 2024
1 parent 01b151c commit b24f6f8
Show file tree
Hide file tree
Showing 2 changed files with 42 additions and 21 deletions.
26 changes: 19 additions & 7 deletions .vitepress/theme/styles.scss
Original file line number Diff line number Diff line change
Expand Up @@ -82,6 +82,12 @@ main {
font-size: 1.7em;
font-weight: 400;
}
h3 + .subtitle {
margin-top: 0;
font-size: 1.1em;
}


p + h1 {
margin-top: 3em
}
Expand Down Expand Up @@ -255,11 +261,11 @@ main {
border-radius: 14px;

&.note {
background-color: #f4f4f4;
border-color: #999;
background-color: #f6f6f6;
border-color: #bbb;
.dark & {
background-color: #444;
&, & code, & a { color: #eee; }
border-color: #666;
background-color: #222;
}
}
&.tip {
Expand Down Expand Up @@ -329,9 +335,15 @@ main {
img.zoom33 { zoom: 33% }
img.zoom25 { zoom: 25% }

.good { color:teal }
.red { color:#e00 }; .green { color:#0a0 };
.bad, .important { color:darkred }; .dark & { .bad, .important { color:#e00 } }
.best-practice::after { content: ' — Best Practice'; color: #777; font-style: italic; }
.anti-pattern::after { content: ' — Anti Pattern'; color: #e00 }
.prefer::before { content: 'Prefer: '; color: #0a0 }
.avoid::before { content: 'Avoid: '; color: #e00 }

.good .green { color:#0a0 };
.bad, .red, .important { color:darkred; .dark & { color:#e00 } }
.grey { color:#777 };

.constructor::before { content: 'Constructor: '; color: #999 }
.annotation::before { content: 'Annotation: '; color: #999 }
.property::before { content: 'Property: '; color: #999 }
Expand Down
37 changes: 23 additions & 14 deletions cds/aspects.md
Original file line number Diff line number Diff line change
Expand Up @@ -34,7 +34,7 @@ Use aspects to factor out secondary concerns into separate files as follows...



### Avoid all-in-one models
### All-in-one models {.avoid}

Instead of polluting your core domain models with a multitude of annotations, put such annotations into separate files. For example, instead of having a single-source model like that:

Expand Down Expand Up @@ -77,7 +77,7 @@ service CatalogService {
```
:::

### Keep your core clean
### Keep your core clean {.prefer}

Rather keep your core model concise and comprehensible:

Expand All @@ -90,7 +90,7 @@ service CatalogService {
```
:::

### Factor out separate concerns
### Factor out separate concerns {.prefer}

And factor out the UI concerns into a separate file like that:

Expand Down Expand Up @@ -150,7 +150,7 @@ Quite frequently, you want some common aspects be factored out and shared by and



### Classic Class-based Approach
### _Max Base Class_ Approach {.avoid}

The classic way to do so, for example in class-based inheritance systems like Java, is to have a central team defining single base classes like `Object` for that, and either add all the aspects in question to that single base class, or have a base class hierarchy, like that:

Expand Down Expand Up @@ -214,7 +214,16 @@ One issue is that due to single inheritance limitations, these base classes freq

:::

### Prefer: Separate Reuse Aspects
::: details `abstract entity` is deprecated...

If you try to use `abstract entity` in CDS, you'll get a warning that it is deprecated.
Reason for that we found it was used mostly for the _'Max Base Class'_ anti pattern.
So we decided to deprecate it to encourage the use of [_Separate Reuse Aspects_](#separate-reuse-aspects) pattern instead.

:::


### Separate Reuse Aspects {.prefer}

While, as shown above, the central single-inheritance-style base class approach is also possible with CDS, we can do better using CDS Aspects, leveraging the equivalent of multiple inheritance, and hence distributed ownership instead of central one:

Expand Down Expand Up @@ -298,7 +307,7 @@ type CodeList : {

:::

### Adding / Adapting Fields
### Adding / Adapting Fields {.best-practice}

Now also assumed, you'd want all code lists to have an additional field for long descriptions, and you also want currency symbols, and the `locale` field for languages needs to support values with up to 15 characters. With aspects, you could simply adapt the reuse types and entities accordingly as follows:

Expand All @@ -313,7 +322,7 @@ extend Languages:locale with (length:15);

:::

### Adding Relationships
### Adding Relationships {.best-practice}

You can even add [Associations](cdl#associations) and [Compositions](cdl#compositions) to definitions you obtained from somewhere else. For example, the following would extend the common reuse type `managed` obtained from `@sap/cds/common` to not only capture latest modifications, but a history of commented changes, with all entities inheriting from that aspect, own or reused ones, receiving this enhancement automatically:

Expand All @@ -332,7 +341,7 @@ extend managed with {



### Adding Reuse Aspects
### Adding Reuse Aspects {.best-practice}

And as the `:` notation to *inherit* an aspect is essentially just [syntactical sugar](cdl#includes) to extending a given definition with a [*named* aspect](cdl#named-aspects), you can also adapt a reused definition to *inherit* from a common reuse aspect from 'the outside' like so:

Expand All @@ -352,7 +361,7 @@ The same approach and techniques is used by SaaS customers when customizing a Sa



### Adding Custom Fields
### Adding Custom Fields {.best-practice}

For example, SaaS customers would quite frequently add extension fields like that:

Expand All @@ -368,7 +377,7 @@ extend ShipmentOrders with {



### Overriding Annotations
### Overriding Annotations {.best-practice}

Sometimes they'd need to override existing annotations, such as for UI labels:

Expand All @@ -379,7 +388,7 @@ annotate Customers with @title:'Patients'; // e.g. for health care



### Verticalization
### Verticalization {.best-practice}

Verticalization means to adapt a given application for different regions or industries, which can be accomplished by providing respective pre-defined extension packages and switch them on per customer using [feature toggles](../guides/extensibility/feature-toggles).

Expand All @@ -405,7 +414,7 @@ entity Groups : Grantees {

When combining that with relational persistence, you'll always end up in trade-off decisions about which strategy to choose for mapping such class hierarchies to flat tables. As that choice heavily depends on the use cases, CDS intentionally doesn't provide any automatic mapping of such inheritance hierarchies, but you have to choose one of the [three commonly known approaches](https://wiki.c2.com/?MappingInheritanceHierarchiesToRelationalSchemataInvolvesCompromises) explicitly in your models as follows...

### Table per leaf class strategy
### Table per leaf class strategy {.avoid}

If we'd keep the model as given above, we'd end up with two separate tables, one for each leaf entity. Problem with that approach is that we'd need expensive UNIONs to, for example, display a heterogeneous list of Users and Groups. For example:

Expand All @@ -419,7 +428,7 @@ entity UsersAndGroups as (



### Table per class strategy
### Table per class strategy {.avoid}

If we want a separate table for each entity in our model above, including the 'superclass' entity `Grantees`, we'd have to rewrite our model to use composition over inheritance like that:

Expand All @@ -441,7 +450,7 @@ This would allow to display heterogeneous lists of `Grantees` without UNIONs. A



### Single table strategy
### Single table strategy {.prefer}

The third strategy is to put everything into a single table and an additional type discriminator element (→ `kind` in the sample below).

Expand Down

0 comments on commit b24f6f8

Please sign in to comment.