|
| 1 | +# ADR-001: Application Architecture |
| 2 | + |
| 3 | +**Status:** Accepted |
| 4 | +**Date:** 2025-12-09 |
| 5 | +**Decision Makers:** Azure Naming Tool Team |
| 6 | +**Version:** 5.0.0 |
| 7 | + |
| 8 | +## Context |
| 9 | + |
| 10 | +The Azure Naming Tool is a web-based application designed to help administrators define and manage Azure resource naming conventions while providing a simple interface for users to generate compliant names. The tool needed an architecture that supports: |
| 11 | + |
| 12 | +- Modern web UI with interactive components |
| 13 | +- RESTful API for programmatic access |
| 14 | +- Flexible configuration management |
| 15 | +- Both human and machine interaction patterns |
| 16 | +- Scalability for enterprise use |
| 17 | +- Easy deployment across multiple hosting platforms |
| 18 | + |
| 19 | +## Decision |
| 20 | + |
| 21 | +We have adopted a **Blazor Server-based architecture** using ASP.NET Core with the following key architectural components: |
| 22 | + |
| 23 | +### Technology Stack |
| 24 | +- **.NET 10.0** - Latest LTS framework for performance, security, and modern features |
| 25 | +- **Blazor Server** - Interactive server-rendered UI with SignalR for real-time communication |
| 26 | +- **ASP.NET Core Web API** - RESTful API endpoints for programmatic access |
| 27 | +- **Entity Framework Core** - Data access layer with provider abstraction |
| 28 | +- **Repository Pattern** - Abstraction layer for storage providers |
| 29 | + |
| 30 | +### Architectural Layers |
| 31 | + |
| 32 | +#### 1. Presentation Layer |
| 33 | +- **Blazor Components** (`Components/`) - Interactive UI built with Razor components |
| 34 | + - Server-side rendering with WebSocket (SignalR) connectivity |
| 35 | + - Component-based architecture for reusability |
| 36 | + - Modal dialogs using Blazored.Modal |
| 37 | + - Toast notifications using Blazored.Toast |
| 38 | + - State management via StateContainer singleton |
| 39 | + |
| 40 | +#### 2. API Layer |
| 41 | +- **REST Controllers** (`Controllers/`) - HTTP endpoints for external integration |
| 42 | + - API Versioning (v1 and v2) with backward compatibility |
| 43 | + - Swagger/OpenAPI documentation |
| 44 | + - API key authentication via custom attributes |
| 45 | + - Rate limiting middleware |
| 46 | + - Correlation ID tracking for distributed tracing |
| 47 | + |
| 48 | +#### 3. Business Logic Layer |
| 49 | +- **Services** (`Services/`) - Core business logic and orchestration |
| 50 | + - `AzureValidationService` - Azure tenant name validation |
| 51 | + - `StorageMigrationService` - Data migration between providers |
| 52 | + - Service interfaces for dependency injection and testing |
| 53 | + |
| 54 | +#### 4. Data Access Layer |
| 55 | +- **Repositories** (`Repositories/`) - Abstract storage operations |
| 56 | + - Interface-based design (`Repositories/Interfaces/`) |
| 57 | + - Multiple implementations: |
| 58 | + - `SQLiteStorageProvider` - Entity Framework Core with SQLite |
| 59 | + - `FileSystemStorageProvider` - JSON file-based storage |
| 60 | + - Repository pattern isolates storage concerns from business logic |
| 61 | + |
| 62 | +#### 5. Domain Layer |
| 63 | +- **Models** (`Models/`) - Domain entities and data transfer objects |
| 64 | + - Configuration entities (ResourceType, ResourceLocation, etc.) |
| 65 | + - Request/Response DTOs for API |
| 66 | + - Validation attributes |
| 67 | + |
| 68 | +#### 6. Cross-Cutting Concerns |
| 69 | +- **Helpers** (`Helpers/`) - Utility functions |
| 70 | + - CacheHelper - In-memory caching |
| 71 | + - ConfigurationHelper - Settings management |
| 72 | + - FileSystemHelper - File operations |
| 73 | + - ValidationHelper - Input validation |
| 74 | + - LogHelper - Structured logging |
| 75 | +- **Middleware** (`Middleware/`) - Request pipeline components |
| 76 | + - ApiLoggingMiddleware - Request/response logging with sanitization |
| 77 | + - CorrelationIdMiddleware - Distributed tracing support |
| 78 | +- **Health Checks** (`HealthChecks/`) - Application health monitoring |
| 79 | + - CacheHealthCheck - Memory cache status |
| 80 | + - StorageHealthCheck - Database/file system connectivity |
| 81 | + |
| 82 | +### Design Patterns |
| 83 | + |
| 84 | +1. **Repository Pattern** - Abstracts data access, allowing storage provider swapping |
| 85 | +2. **Dependency Injection** - All services registered via .NET DI container |
| 86 | +3. **Options Pattern** - Configuration bound to strongly-typed classes |
| 87 | +4. **Strategy Pattern** - Multiple storage providers (SQLite, FileSystem) |
| 88 | +5. **API Versioning** - Backwards-compatible API evolution (v1, v2) |
| 89 | + |
| 90 | +### API Architecture |
| 91 | + |
| 92 | +The application exposes two API versions: |
| 93 | + |
| 94 | +- **API v1.0** - Current stable API with backward compatibility |
| 95 | + - Traditional controller endpoints |
| 96 | + - Single resource operations |
| 97 | + |
| 98 | +- **API v2.0** - Enhanced API with modern features |
| 99 | + - Bulk operations support |
| 100 | + - Enhanced filtering and sorting |
| 101 | + - Improved error responses with detailed messages |
| 102 | + - Consistent response format with ApiResponse wrapper |
| 103 | + |
| 104 | +API endpoints support: |
| 105 | +- JSON request/response with camelCase naming |
| 106 | +- Enum serialization as strings (human-readable) |
| 107 | +- OpenAPI/Swagger documentation |
| 108 | +- API key authentication |
| 109 | +- Rate limiting and throttling |
| 110 | + |
| 111 | +## Consequences |
| 112 | + |
| 113 | +### Positive |
| 114 | + |
| 115 | +✅ **Modern Development Experience** |
| 116 | +- .NET 10.0 provides latest language features and performance improvements |
| 117 | +- Hot reload support for rapid development |
| 118 | +- Strong typing throughout the application |
| 119 | + |
| 120 | +✅ **Scalability** |
| 121 | +- Blazor Server scales well with SignalR load balancing |
| 122 | +- Repository pattern allows easy migration to different storage backends |
| 123 | +- API versioning enables non-breaking feature additions |
| 124 | + |
| 125 | +✅ **Maintainability** |
| 126 | +- Clear separation of concerns across layers |
| 127 | +- Dependency injection simplifies testing and mocking |
| 128 | +- Interface-based design allows implementation swapping |
| 129 | + |
| 130 | +✅ **Flexibility** |
| 131 | +- Multiple storage providers (SQLite for performance, FileSystem for simplicity) |
| 132 | +- Multiple authentication methods (API keys, configurable in future) |
| 133 | +- Dual access patterns (UI and API) |
| 134 | + |
| 135 | +✅ **Developer Productivity** |
| 136 | +- Blazor components enable rapid UI development |
| 137 | +- Shared C# code between client and server logic |
| 138 | +- Comprehensive Swagger documentation for API consumers |
| 139 | + |
| 140 | +### Negative |
| 141 | + |
| 142 | +⚠️ **Blazor Server Limitations** |
| 143 | +- Requires persistent WebSocket connection (SignalR) |
| 144 | +- Not suitable for offline scenarios |
| 145 | +- Higher server resource usage compared to static sites |
| 146 | +- Network latency affects UI responsiveness |
| 147 | + |
| 148 | +⚠️ **Complexity** |
| 149 | +- Multiple abstraction layers may be overkill for small deployments |
| 150 | +- Repository pattern adds indirection |
| 151 | +- Dual storage provider support requires careful testing |
| 152 | + |
| 153 | +⚠️ **Dependencies** |
| 154 | +- Requires .NET 10.0 runtime (breaking change from .NET 8.0) |
| 155 | +- SQLite native libraries required for database provider |
| 156 | +- SignalR requires WebSocket support in hosting environment |
| 157 | + |
| 158 | +### Mitigations |
| 159 | + |
| 160 | +- Circuit timeouts and retry logic configured for unreliable networks |
| 161 | +- Storage provider abstraction allows fallback to FileSystem |
| 162 | +- Comprehensive health checks detect configuration issues early |
| 163 | +- Migration tools help users upgrade between storage providers |
| 164 | + |
| 165 | +## Alternatives Considered |
| 166 | + |
| 167 | +### 1. Blazor WebAssembly |
| 168 | +**Rejected** - Would require duplicating storage logic on client, no server-side validation benefits, larger initial download size. |
| 169 | + |
| 170 | +### 2. Traditional MVC with JavaScript |
| 171 | +**Rejected** - Less interactive UI, more complex state management, dual language maintenance (C# + JS). |
| 172 | + |
| 173 | +### 3. Single Storage Provider (SQLite only) |
| 174 | +**Rejected** - Would break backward compatibility for existing deployments, removes deployment flexibility. |
| 175 | + |
| 176 | +### 4. Microservices Architecture |
| 177 | +**Rejected** - Over-engineered for current scale, unnecessary operational complexity, single-application scope doesn't justify distributed architecture. |
| 178 | + |
| 179 | +## References |
| 180 | + |
| 181 | +- [Microsoft Cloud Adoption Framework - Naming Conventions](https://learn.microsoft.com/azure/cloud-adoption-framework/ready/azure-best-practices/naming-and-tagging) |
| 182 | +- [Blazor Server Documentation](https://learn.microsoft.com/aspnet/core/blazor/hosting-models#blazor-server) |
| 183 | +- [ASP.NET Core API Versioning](https://github.com/dotnet/aspnet-api-versioning) |
| 184 | +- [Repository Pattern in .NET](https://learn.microsoft.com/dotnet/architecture/microservices/microservice-ddd-cqrs-patterns/infrastructure-persistence-layer-design) |
| 185 | + |
| 186 | +## Related ADRs |
| 187 | + |
| 188 | +- [ADR-002: Hosting Architecture](ADR-002-hosting-architecture.md) |
| 189 | +- [ADR-003: Data Storage Architecture](ADR-003-data-storage-architecture.md) |
0 commit comments