Skip to content

Commit c62cea8

Browse files
committed
chore: update value-object building block
1 parent f951d19 commit c62cea8

1 file changed

Lines changed: 29 additions & 1 deletion

File tree

.agents/skills/building-blocks/rules/value-object.md

Lines changed: 29 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -13,11 +13,12 @@ Classes with static methods encapsulating domain logic and correlated utilities
1313

1414
- All methods are static — value objects are namespaces with type safety, not instances with state.
1515
- Group by concept, not by operation type. `Price.format()`, `Price.isValid()`, `Price.fromCents()` — not a `formatters.ts` file with `formatPrice`, `formatDate`, `formatName`.
16-
- Can be also defined for domain concepts, for e-commerce for instance `Product.getRating()`.
16+
- For domain computations, the value object belongs to the feature that owns the result. Cart total → `Cart.calculateTotal(items)`, not a loose `calculateCartTotal` utility.
1717

1818
### Example
1919

2020
```tsx
21+
// src/lib/format
2122
export class Price {
2223
static format(amount: number, currency = "USD"): string {
2324
return new Intl.NumberFormat("en-US", {
@@ -36,9 +37,36 @@ export class Price {
3637
}
3738
```
3839

40+
```tsx
41+
// Domain computation spanning multiple objects — belongs to the concept that owns the result
42+
// src/features/carts/application
43+
export class Cart {
44+
private static readonly DISCOUNT_THRESHOLD = 100;
45+
private static readonly DISCOUNT_PERCENT = 10;
46+
47+
static calculateTotal(items: CartItem[]): number {
48+
const subtotal = items.reduce(
49+
(sum, item) => sum + item.price * item.quantity,
50+
0
51+
);
52+
53+
return Cart.isEligibleForDiscount(subtotal)
54+
? subtotal * (1 - Cart.DISCOUNT_PERCENT / 100)
55+
: subtotal;
56+
}
57+
58+
private static isEligibleForDiscount(subtotal: number): boolean {
59+
return subtotal >= Cart.DISCOUNT_THRESHOLD;
60+
}
61+
}
62+
```
63+
3964
```tsx
4065
// Usage — all price-related logic in one place
4166
Price.format(product.price); // "$29.99"
4267
Price.fromCents(2999); // 29.99
4368
Price.isValid(product.price); // true
69+
70+
// Usage - use Value Object rather than loose utilities
71+
Cart.calculateTotal(products);
4472
```

0 commit comments

Comments
 (0)