クロードのアーキテクチャ: バックエンドとフロントエンド
建築デザインは、クロードが最も得意とする分野の 1 つです。 クロードは明晰な推論のおかげで、あなたの探求を手助けします トレード・オフ、 アーキテクチャ パターンを比較し、影響を与える情報に基づいた意思決定を行う プロジェクトのライフサイクル全体。
この記事では、Claude を使用してバックエンド アーキテクチャを設計する方法を説明します。 と スプリングブーツ そしてフロントエンドで 角度のある、申請中 ソリューション アーキテクチャのベスト プラクティス。
何を学ぶか
- トレードオフのあるアーキテクチャ上の決定に Claude を使用する
- クリーン/ヘキサゴナル アーキテクチャを使用した Spring Boot バックエンドの設計
- スケーラブルなパターンを使用した Angular フロントエンドの構造化
- フロントエンドとバックエンド間のAPIコントラクトを定義する
- バージョン管理とエラー処理を管理する
建築におけるクロードの役割
クロードは次の役割を担うことができます ソリューションアーキテクト あなたを導くことです 複雑な意思決定を通じて。重要なのは、十分なコンテキストを提供することです。 トレードオフ分析を明示的に要求します。
You are a Senior Solution Architect with 15+ years of experience
in enterprise software development.
EXPERTISE:
- Microservices architecture (Spring Boot, Kubernetes)
- Frontend architecture (Angular, React, Vue)
- Event-driven systems (Kafka, RabbitMQ)
- Cloud platforms (AWS, Azure, GCP)
- DDD, Clean Architecture, Hexagonal
COMMUNICATION STYLE:
- Always explain trade-offs for every recommendation
- Use diagrams (ASCII or Mermaid) when helpful
- Cite industry standards (12-factor app, SOLID, etc.)
- Challenge assumptions when they seem problematic
CONSTRAINTS:
- Prioritize maintainability over cleverness
- Consider team size and skill level
- Focus on practical, implementable solutions
- Always address security implications
バックエンド アーキテクチャ: Spring Boot
推奨されるアーキテクチャ パターン
バックエンドパターンの比較
| パターン | 複雑 | いつ使用するか | トレードオフ |
|---|---|---|---|
| 階層化 (MVC) | 低い | シンプルな CRUD、MVP | 柔軟性が低く、結合度が高い |
| クリーンなアーキテクチャ | 平均 | 複雑なビジネスロジック | より多くのコード、学習曲線 |
| 六角 | 中~高 | 複数の統合、テスト容易性 | 初期オーバーヘッド、ポート/アダプター |
| CQRS | 高い | 非対称読み取り/書き込み、スケーラビリティ | インフラストラクチャの複雑さ |
例: Spring Boot を使用したヘキサゴナル アーキテクチャ
<role>Sei un Senior Backend Architect specializzato in Spring Boot</role>
<context>
Progetto: Order Management per e-commerce
Stack: Spring Boot 3.2, PostgreSQL, Redis, Kafka
Team: 4 developers mid-level
Requisiti:
- CRUD ordini con stati complessi
- Integrazione payment gateway (Stripe)
- Notifiche async (email, push)
- Audit trail completo
</context>
<task>
Progetta una Hexagonal Architecture per l'Order Service.
Includi:
1. Struttura package completa
2. Definizione Ports (inbound/outbound)
3. Adapters per ogni integration
4. Use Cases principali
</task>
<output_format>
- Diagramma ASCII o Mermaid
- Struttura cartelle
- Interfacce chiave con signature
- Spiegazione delle scelte
</output_format>
order-service/
├── src/main/java/com/company/orders/
│ ├── domain/ # Core Business Logic
│ │ ├── model/
│ │ │ ├── Order.java # Aggregate Root
│ │ │ ├── OrderItem.java
│ │ │ ├── OrderStatus.java # Enum stati
│ │ │ └── Money.java # Value Object
│ │ ├── service/
│ │ │ └── OrderDomainService.java
│ │ └── event/
│ │ └── OrderEvent.java # Domain Events
│ │
│ ├── application/ # Use Cases / Ports
│ │ ├── port/
│ │ │ ├── in/ # Inbound Ports
│ │ │ │ ├── CreateOrderUseCase.java
│ │ │ │ ├── UpdateOrderStatusUseCase.java
│ │ │ │ └── GetOrderQuery.java
│ │ │ └── out/ # Outbound Ports
│ │ │ ├── OrderRepository.java
│ │ │ ├── PaymentGateway.java
│ │ │ ├── NotificationSender.java
│ │ │ └── EventPublisher.java
│ │ └── service/
│ │ └── OrderApplicationService.java
│ │
│ ├── adapter/ # Infrastructure
│ │ ├── in/ # Inbound Adapters
│ │ │ ├── web/
│ │ │ │ ├── OrderController.java
│ │ │ │ ├── dto/
│ │ │ │ │ ├── CreateOrderRequest.java
│ │ │ │ │ └── OrderResponse.java
│ │ │ │ └── mapper/
│ │ │ │ └── OrderDtoMapper.java
│ │ │ └── event/
│ │ │ └── OrderEventListener.java
│ │ └── out/ # Outbound Adapters
│ │ ├── persistence/
│ │ │ ├── OrderJpaRepository.java
│ │ │ ├── OrderPersistenceAdapter.java
│ │ │ └── entity/
│ │ │ └── OrderJpaEntity.java
│ │ ├── payment/
│ │ │ └── StripePaymentAdapter.java
│ │ ├── notification/
│ │ │ ├── EmailNotificationAdapter.java
│ │ │ └── PushNotificationAdapter.java
│ │ └── messaging/
│ │ └── KafkaEventPublisher.java
│ │
│ └── config/ # Spring Configuration
│ ├── BeanConfiguration.java
│ ├── PersistenceConfig.java
│ └── KafkaConfig.java
主要なインターフェイス (ポート)
public interface CreateOrderUseCase {{ '{' }}
/**
* Crea un nuovo ordine validando disponibilità prodotti
* e iniziando il processo di pagamento.
*
* @param command contiene items, customer, payment info
* @return OrderId dell'ordine creato
* @throws InsufficientStockException se prodotti non disponibili
* @throws PaymentInitializationException se payment fallisce
*/
OrderId execute(CreateOrderCommand command);
{{ '}' }}
public record CreateOrderCommand(
CustomerId customerId,
List<OrderItemCommand> items,
ShippingAddress address,
PaymentMethod paymentMethod
) {{ '{' }}{{ '}' }}
public interface PaymentGateway {{ '{' }}
/**
* Inizia una transazione di pagamento.
* Non completa il pagamento, solo lo inizializza.
*
* @param request dati pagamento
* @return PaymentIntent con clientSecret per frontend
*/
PaymentIntent initializePayment(PaymentRequest request);
/**
* Conferma un pagamento già autorizzato.
*
* @param paymentIntentId ID del payment intent
* @return risultato conferma
*/
PaymentConfirmation confirmPayment(String paymentIntentId);
/**
* Esegue refund parziale o totale.
*/
RefundResult refund(String paymentIntentId, Money amount);
{{ '}' }}
フロントエンド アーキテクチャ: Angular
Angular の推奨パターン
Angular フロントエンド パターン
| パターン | 複雑 | いつ使用するか |
|---|---|---|
| 機能ベース | 低い | 小規模/中規模プロジェクト、単一チーム |
| スマート/ダムコンポーネント | 平均 | 再利用性、テスト容易性 |
| 信号 + サービス | 平均 | 最新の状態管理、Angular 17+ |
| NGRx | 高い | エンタープライズ、複雑な状態、高度なデバッグ |
例: シグナルを使用した機能ベース
src/app/
├── core/ # Servizi singleton
│ ├── services/
│ │ ├── api.service.ts # HTTP client base
│ │ ├── auth.service.ts
│ │ └── notification.service.ts
│ ├── guards/
│ │ └── auth.guard.ts
│ ├── interceptors/
│ │ ├── auth.interceptor.ts
│ │ └── error.interceptor.ts
│ └── models/
│ └── api-response.model.ts
│
├── shared/ # Componenti riutilizzabili
│ ├── components/
│ │ ├── button/
│ │ ├── modal/
│ │ ├── table/
│ │ └── form-field/
│ ├── pipes/
│ │ └── currency-format.pipe.ts
│ └── directives/
│ └── click-outside.directive.ts
│
├── features/ # Feature modules
│ ├── orders/
│ │ ├── components/
│ │ │ ├── order-list/ # Smart component
│ │ │ │ ├── order-list.component.ts
│ │ │ │ └── order-list.component.html
│ │ │ ├── order-card/ # Dumb component
│ │ │ │ ├── order-card.component.ts
│ │ │ │ └── order-card.component.html
│ │ │ └── order-detail/
│ │ ├── services/
│ │ │ └── order.service.ts # State + API
│ │ ├── models/
│ │ │ └── order.model.ts
│ │ └── orders.routes.ts
│ │
│ ├── products/
│ └── customers/
│
├── layouts/
│ ├── main-layout/
│ └── auth-layout/
│
└── app.routes.ts
信号によるサービス
@Injectable({{ '{' }} providedIn: 'root' {{ '}' }})
export class OrderService {{ '{' }}
private http = inject(HttpClient);
// State
private ordersSignal = signal<Order[]>([]);
private loadingSignal = signal(false);
private errorSignal = signal<string | null>(null);
private selectedOrderSignal = signal<Order | null>(null);
// Public readonly signals
readonly orders = this.ordersSignal.asReadonly();
readonly loading = this.loadingSignal.asReadonly();
readonly error = this.errorSignal.asReadonly();
readonly selectedOrder = this.selectedOrderSignal.asReadonly();
// Computed signals
readonly pendingOrders = computed(() =>
this.ordersSignal().filter(o => o.status === 'PENDING')
);
readonly orderStats = computed(() => ({{ '{' }}
total: this.ordersSignal().length,
pending: this.pendingOrders().length,
totalRevenue: this.ordersSignal()
.filter(o => o.status === 'COMPLETED')
.reduce((sum, o) => sum + o.total, 0)
{{ '}' }}));
loadOrders(): void {{ '{' }}
this.loadingSignal.set(true);
this.errorSignal.set(null);
this.http.get<Order[]>('/api/orders').pipe(
catchError(err => {{ '{' }}
this.errorSignal.set('Errore nel caricamento ordini');
return of([]);
{{ '}' }}),
finalize(() => this.loadingSignal.set(false))
).subscribe(orders => this.ordersSignal.set(orders));
{{ '}' }}
createOrder(order: CreateOrderDto): Observable<Order> {{ '{' }}
return this.http.post<Order>('/api/orders', order).pipe(
tap(newOrder => {{ '{' }}
this.ordersSignal.update(orders => [...orders, newOrder]);
{{ '}' }})
);
{{ '}' }}
selectOrder(orderId: string): void {{ '{' }}
const order = this.ordersSignal().find(o => o.id === orderId);
this.selectedOrderSignal.set(order ?? null);
{{ '}' }}
{{ '}' }}
API コントラクト: フロントエンド - バックエンド
<task>
Definisci l'API contract REST per la gestione ordini.
Requisiti:
- RESTful con risorse annidate dove appropriato
- Paginazione per liste
- Error response standardizzate
- Versioning nell'URL (/api/v1/)
- HATEOAS links (opzionale)
</task>
<output_format>
Per ogni endpoint:
- Metodo HTTP + Path
- Request body (se POST/PUT)
- Response body con codici HTTP
- Esempi JSON
</output_format>
## Orders API v1
### Create Order
POST /api/v1/orders
Content-Type: application/json
Request:
{{ '{' }}
"customerId": "cust_123",
"items": [
{{ '{' }} "productId": "prod_456", "quantity": 2 {{ '}' }}
],
"shippingAddress": {{ '{' }}
"street": "Via Roma 1",
"city": "Milano",
"zipCode": "20100"
{{ '}' }},
"paymentMethod": "CARD"
{{ '}' }}
Response 201 Created:
{{ '{' }}
"id": "ord_789",
"status": "PENDING_PAYMENT",
"total": 99.99,
"createdAt": "2025-02-01T10:00:00Z",
"_links": {{ '{' }}
"self": {{ '{' }} "href": "/api/v1/orders/ord_789" {{ '}' }},
"payment": {{ '{' }} "href": "/api/v1/orders/ord_789/payment" {{ '}' }}
{{ '}' }}
{{ '}' }}
Response 400 Bad Request:
{{ '{' }}
"type": "validation_error",
"title": "Validation Failed",
"status": 400,
"errors": [
{{ '{' }}
"field": "items",
"message": "At least one item required"
{{ '}' }}
]
{{ '}' }}
### Get Orders (Paginated)
GET /api/v1/orders?page=0&size=20&status=PENDING
Response 200 OK:
{{ '{' }}
"content": [...],
"page": {{ '{' }}
"number": 0,
"size": 20,
"totalElements": 150,
"totalPages": 8
{{ '}' }}
{{ '}' }}
標準化されたエラー処理
// Backend: GlobalExceptionHandler.java
@RestControllerAdvice
public class GlobalExceptionHandler {{ '{' }}
@ExceptionHandler(OrderNotFoundException.class)
public ResponseEntity<ProblemDetail> handleNotFound(
OrderNotFoundException ex) {{ '{' }}
ProblemDetail problem = ProblemDetail.forStatusAndDetail(
HttpStatus.NOT_FOUND,
ex.getMessage()
);
problem.setType(URI.create("/errors/order-not-found"));
problem.setTitle("Order Not Found");
problem.setProperty("orderId", ex.getOrderId());
return ResponseEntity.status(404).body(problem);
{{ '}' }}
@ExceptionHandler(PaymentFailedException.class)
public ResponseEntity<ProblemDetail> handlePaymentFailed(
PaymentFailedException ex) {{ '{' }}
ProblemDetail problem = ProblemDetail.forStatusAndDetail(
HttpStatus.PAYMENT_REQUIRED,
"Payment processing failed"
);
problem.setType(URI.create("/errors/payment-failed"));
problem.setProperty("reason", ex.getReason());
problem.setProperty("retryable", ex.isRetryable());
return ResponseEntity.status(402).body(problem);
{{ '}' }}
{{ '}' }}
// error.interceptor.ts
export const errorInterceptor: HttpInterceptorFn = (req, next) => {{ '{' }}
const notification = inject(NotificationService);
return next(req).pipe(
catchError((error: HttpErrorResponse) => {{ '{' }}
const problemDetail = error.error as ProblemDetail;
switch (error.status) {{ '{' }}
case 400:
notification.showError(
problemDetail.title ?? 'Validation Error'
);
break;
case 401:
// Redirect to login
break;
case 404:
notification.showWarning(
problemDetail.detail ?? 'Resource not found'
);
break;
case 500:
notification.showError(
'Server error. Please try again later.'
);
break;
{{ '}' }}
return throwError(() => error);
{{ '}' }})
);
{{ '}' }};
建築チェックリスト
開発開始前のチェックリスト
- バックエンドのアーキテクチャ パターンの定義と文書化
- 合意されたフロントエンド/バックエンドのフォルダー構造
- API 契約を例とともに文書化
- 標準化されたエラー処理 (RFC 7807)
- API バージョン管理戦略の定義
- 合意された命名規則
- ADRに文書化された決定
結論と次のステップ
この記事では、Claude を使用してアーキテクチャを設計する方法について説明しました。 Spring Boot バックエンドと Angular フロントエンドではソリッド。私たちは次のことを調査しました。
- アーキテクチャのパターンとトレードオフ
- Spring Boot を使用したヘキサゴナル アーキテクチャ
- Angular と Signals を使用した機能ベースの構造
- APIコントラクト設計
- 標準化されたエラー処理
Nel 次の記事、さらに深く掘り下げていきます 構造 コードの: フォルダー構成、命名規則、分離 懸念事項や構成管理についても説明します。
覚えておくべき重要なポイント
- まずはトレードオフ: 常にクロードに長所/短所を分析するように依頼してください
- 統合用の六角形: ビジネス ロジックを技術的な詳細から分離する
- Angular 17 以降のシグナル: シンプルで応答性の高い状態管理
- 契約API: 実装する前に定義する
- 決定事項を文書化する: ADR を使用して選択肢を追跡する







