The Three-Layer Architecture
The three-layer architecture is a structural pattern commonly applied to API applications (such as those built with FastAPI) to separate concerns and improve maintainability.
- Data Layer:
- Handles direct database operations.
- Contains no business logic.
- Returns raw database results.
- Service Layer:
- Contains the core business logic.
- Handles exceptions and formatting of business errors.
- Orchestrates calls to the data layer.
- Validates business rules.
- API Layer (or Web/Presentation Layer):
- Defines HTTP routes and endpoints.
- Handles HTTP-specific logic (headers, status codes).
- Uses the service layer for operations.
- Maps outputs to response models.
Request Flow
Web Request -> API Layer -> Service Layer -> Data Layer -> Database
Response <- API Layer <- Service Layer <- Data Layer <- Database
Benefits
This separation allows for:
- Better testability (layers can be mocked).
- Cleaner code organization.
- Easier maintenance.
- Clear responsibility boundaries.
- Reusability of business logic.
- Strict separation of concerns.
Example Implementation in FastAPI
1. API Layer (web/article.py)
from fastapi import APIRouter, Depends, Response, status
from sqlalchemy.orm import Session
from schemas.article import ArticleCreate, ArticleShow
from service.article import ArticleService
router = APIRouter(prefix="/articles", tags=["Articles"])
@router.post("/", response_model=ArticleShow, status_code=status.HTTP_201_CREATED)
def create_article(article: ArticleCreate, db: Session = Depends(get_db)):
created_article = ArticleService.create_article(article, db, author_id=1)
return created_article
2. Service Layer (service/article.py)
from fastapi import HTTPException, status
import data.article as data
class ArticleService:
@staticmethod
def create_article(article, db, author_id):
try:
return data.db_create_article(article, db, author_id)
except Exception as e:
raise HTTPException(
status_code=status.HTTP_500_INTERNAL_SERVER_ERROR,
detail=f"Failed to create article: {str(e)}"
)