-
Notifications
You must be signed in to change notification settings - Fork 0
Architecture
This framework is designed to be flexible and support various architectural patterns.
azfunc-boot provides a foundation for building well-structured Azure Functions applications without enforcing a rigid architecture. You can organize your code however you prefer.
The heart of the framework, managing service registration and resolution:
- Service Registration: Register services with different lifetimes
- Automatic Resolution: Resolve dependencies using type annotations
- Scope Management: Create and manage scoped service instances
Organize Azure Functions triggers using a class-based approach:
- Route Organization: Group related routes together
- Automatic Discovery: Controllers are automatically discovered and registered
- Scope Management: Automatic scope creation per request/trigger
Centralized service registration:
- Automatic Discovery: Registries are automatically discovered
- Organized Registration: Group related service registrations
- Flexible Registration: Support for simple and lambda-based registration
The framework supports (but doesn't enforce) various architectural patterns:
Handle HTTP requests and Azure Functions triggers:
class UserController(BaseController):
# Handles HTTP requests, triggers, etc.
passBusiness logic and orchestration (optional):
class UserService:
def __init__(self, repository: IUserRepository):
self.repository = repository
async def create_user(self, data: dict):
# Business logic here
passData access abstraction (optional):
class UserRepository:
def __init__(self, db_context: IDatabaseContext):
self.db = db_context
async def find_by_id(self, user_id: str):
# Data access logic
passBusiness entities (optional):
class User:
def __init__(self, id: str, name: str, email: str):
self.id = id
self.name = name
self.email = emailImportant: The framework doesn't enforce any specific structure. You can:
- Use or skip service layers
- Use or skip repository patterns
- Organize code in any way you prefer
- Mix and match patterns as needed
The only requirements are:
- Controllers must extend
BaseController - Service registries must extend
BaseServiceRegistry
Here's one possible structure (you can organize differently):
project/
├── controllers/
│ ├── __init__.py
│ ├── user_controller.py
│ └── product_controller.py
├── services/
│ ├── __init__.py
│ ├── user_service.py
│ └── product_service.py
├── repositories/
│ ├── __init__.py
│ ├── user_repository.py
│ └── product_repository.py
├── registries/
│ ├── __init__.py
│ ├── services_registry.py
│ └── repositories_registry.py
├── models/
│ ├── __init__.py
│ ├── user.py
│ └── product.py
└── function_app.py
But you could also organize as:
project/
├── features/
│ ├── users/
│ │ ├── controller.py
│ │ ├── service.py
│ │ └── repository.py
│ └── products/
│ ├── controller.py
│ ├── service.py
│ └── repository.py
├── registries/
│ └── services_registry.py
└── function_app.py
Or any other structure that works for your project!
Controller
↓ (depends on)
Service (optional)
↓ (depends on)
Repository (optional)
↓ (depends on)
Database/External Service
The framework automatically discovers:
-
Controllers: All classes extending
BaseControllerin the controllers package -
Service Registries: All classes extending
BaseServiceRegistryin the registries package
This happens during create_app():
app, container = create_app(
controllers_package="controllers",
registries_package="registries"
)- Request/Trigger Starts: A new scope is created
- Service Resolution: Services are resolved within the scope
- Request Processing: Your code executes
-
Scope Ends: Scoped services are disposed (if they implement
IDisposable)
- Flexibility: Organize code however you prefer
- Testability: Easy to mock dependencies
- Maintainability: Clear separation of concerns
- Scalability: Easy to add new features
- Type Safety: Type annotations for better IDE support