【初心者向け】プログラミングの「レイヤー」概念理解

プログラミングにおけるレイヤー(層)の概念を初心者にもわかりやすく解説。アーキテクチャ設計の基礎から実装例まで、段階的に理解できる内容

みなさん、プログラミングを学んでいて「レイヤー」という言葉を聞いたことはありませんか?

「このコードはどのレイヤーに書けばいいの?」「レイヤーを分けるって何のこと?」と疑問に思ったことがあるかもしれません。

この記事では、プログラミングにおけるレイヤー(層)の概念について、身近な例を使いながら初心者にもわかりやすく解説します。きれいで保守しやすいコードを書くための重要な考え方を身につけていきましょう。

レイヤーとは何か

プログラミングにおけるレイヤーとは、システムを機能や責任ごとに分けた「層」のことです。

身近な例で理解する

レイヤーの概念を、レストランの例で考えてみましょう。

# レストランをレイヤーで表現
class RestaurantLayers:
def __init__(self):
# フロント層(お客様とのやり取り)
self.presentation_layer = {
"role": "お客様への対応",
"responsibilities": [
"注文を受ける",
"料理を提供する",
"お会計をする",
"サービス提供"
],
"staff": ["ウェイター", "ホール係"]
}
# ビジネス層(料理の作成)
self.business_layer = {
"role": "料理の調理",
"responsibilities": [
"メニューに従って調理",
"品質管理",
"調理時間の管理",
"盛り付け"
],
"staff": ["シェフ", "調理師"]
}
# データ層(材料の管理)
self.data_layer = {
"role": "材料・在庫管理",
"responsibilities": [
"食材の保管",
"在庫の確認",
"食材の発注",
"品質チェック"
],
"staff": ["倉庫係", "購買担当"]
}
def demonstrate_layer_interaction(self, customer_order):
"""レイヤー間の連携を示す"""
# 1. プレゼンテーション層:注文受付
print(f"ウェイター: 「{customer_order}のご注文ですね」")
# 2. ビジネス層:調理指示
print(f"シェフ: 「{customer_order}を作ります」")
# 3. データ層:材料確認
print(f"倉庫係: 「{customer_order}の材料を確認します」")
# 4. 逆順で完成品が届く
print(f"倉庫係 → シェフ → ウェイター → お客様")
return "料理完成"

このように、それぞれの層が異なる責任を持ち、順序立てて連携することで全体が機能します。

プログラミングでのレイヤーの意義

class LayerBenefits:
"""レイヤー分けのメリット"""
def __init__(self):
self.benefits = {
"separation_of_concerns": {
"description": "関心の分離",
"benefit": "各層が特定の責任に集中できる",
"example": "画面表示の処理と計算処理を分ける"
},
"maintainability": {
"description": "保守性の向上",
"benefit": "変更時の影響範囲が限定される",
"example": "データベースを変更してもビジネス処理には影響しない"
},
"reusability": {
"description": "再利用性",
"benefit": "同じ処理を複数の場所で使える",
"example": "同じビジネス処理をWebとAPIで共有"
},
"testability": {
"description": "テストのしやすさ",
"benefit": "各層を独立してテストできる",
"example": "データベースなしでビジネス処理をテスト"
}
}
def compare_with_without_layers(self):
"""レイヤーありなしの比較"""
comparison = {
"without_layers": {
"code_structure": "すべて一つのファイル・関数に混在",
"change_impact": "小さな変更でも全体に影響",
"testing": "全体をセットアップしないとテスト不可",
"understanding": "コード全体を理解する必要"
},
"with_layers": {
"code_structure": "責任ごとに整理された構造",
"change_impact": "変更の影響が該当層に限定",
"testing": "各層を独立してテスト可能",
"understanding": "関心のある層だけ理解すればOK"
}
}
return comparison

基本的なレイヤー構造

3層アーキテクチャ

最も基本的なレイヤー構造は「3層アーキテクチャ」です。

# 3層アーキテクチャの基本構造
class ThreeLayerArchitecture:
"""3層アーキテクチャの説明"""
def __init__(self):
self.layers = {
"presentation_layer": {
"name": "プレゼンテーション層(表示層)",
"purpose": "ユーザーとのやり取り",
"responsibilities": [
"ユーザー入力の受け取り",
"画面表示の制御",
"エラーメッセージの表示",
"UI/UXの管理"
],
"technologies": ["HTML/CSS", "React", "Vue.js", "Flutter"],
"files_examples": ["views/", "components/", "pages/"]
},
"business_layer": {
"name": "ビジネス層(処理層)",
"purpose": "業務ロジックの実行",
"responsibilities": [
"計算処理",
"業務ルールの適用",
"データの加工・変換",
"外部サービスとの連携"
],
"technologies": ["Java", "Python", "Node.js", "C#"],
"files_examples": ["services/", "controllers/", "handlers/"]
},
"data_layer": {
"name": "データ層(永続化層)",
"purpose": "データの保存・取得",
"responsibilities": [
"データベースアクセス",
"ファイル操作",
"外部API呼び出し",
"データの永続化"
],
"technologies": ["MySQL", "PostgreSQL", "MongoDB", "Redis"],
"files_examples": ["models/", "repositories/", "dao/"]
}
}
def show_data_flow(self):
"""データの流れを示す"""
flow_example = """
ユーザー入力
プレゼンテーション層(入力の受け取り)
ビジネス層(処理の実行)
データ層(データの保存・取得)
ビジネス層(結果の加工)
プレゼンテーション層(結果の表示)
ユーザーに結果表示
"""
return flow_example

実際のコード例

シンプルなユーザー管理システムを例に、レイヤー分けを見てみましょう。

# ❌ レイヤーを分けていない例(悪い例)
def handle_user_registration(request):
# すべてが一つの関数に混在
name = request.get('name')
email = request.get('email')
# バリデーション
if not name or len(name) < 2:
return "名前は2文字以上で入力してください"
if not email or '@' not in email:
return "正しいメールアドレスを入力してください"
# データベースに直接アクセス
import sqlite3
conn = sqlite3.connect('users.db')
cursor = conn.cursor()
# 重複チェック
cursor.execute("SELECT * FROM users WHERE email = ?", (email,))
if cursor.fetchone():
return "このメールアドレスは既に登録されています"
# ユーザー作成
cursor.execute("INSERT INTO users (name, email) VALUES (?, ?)", (name, email))
conn.commit()
conn.close()
# HTMLを直接生成
return f"""
<html>
<body>
<h1>登録完了</h1>
<p>{name}様、登録ありがとうございます</p>
</body>
</html>
"""
# ✅ レイヤーを分けた例(良い例)
# データ層
class UserRepository:
"""ユーザーデータの永続化を担当"""
def __init__(self):
self.db = Database()
def save_user(self, user):
"""ユーザーをデータベースに保存"""
return self.db.execute(
"INSERT INTO users (name, email) VALUES (?, ?)",
(user.name, user.email)
)
def find_by_email(self, email):
"""メールアドレスでユーザーを検索"""
return self.db.query(
"SELECT * FROM users WHERE email = ?",
(email,)
)
# ビジネス層
class UserService:
"""ユーザー関連のビジネスロジックを担当"""
def __init__(self, user_repository):
self.user_repository = user_repository
def register_user(self, name, email):
"""ユーザー登録の処理"""
# バリデーション
validation_result = self.validate_user_data(name, email)
if not validation_result.is_valid:
raise ValidationError(validation_result.error_message)
# 重複チェック
existing_user = self.user_repository.find_by_email(email)
if existing_user:
raise DuplicateUserError("このメールアドレスは既に登録されています")
# ユーザー作成
user = User(name=name, email=email)
return self.user_repository.save_user(user)
def validate_user_data(self, name, email):
"""ユーザーデータのバリデーション"""
if not name or len(name) < 2:
return ValidationResult(False, "名前は2文字以上で入力してください")
if not email or '@' not in email:
return ValidationResult(False, "正しいメールアドレスを入力してください")
return ValidationResult(True, None)
# プレゼンテーション層
class UserController:
"""ユーザー関連のHTTPリクエストを処理"""
def __init__(self, user_service):
self.user_service = user_service
def register(self, request):
"""ユーザー登録のHTTPエンドポイント"""
try:
name = request.get('name')
email = request.get('email')
# ビジネス層に処理を委譲
user = self.user_service.register_user(name, email)
# 成功レスポンス
return self.render_success_page(user)
except ValidationError as e:
return self.render_error_page(e.message)
except DuplicateUserError as e:
return self.render_error_page(e.message)
def render_success_page(self, user):
"""成功画面の生成"""
return f"""
<html>
<body>
<h1>登録完了</h1>
<p>{user.name}様、登録ありがとうございます</p>
</body>
</html>
"""
def render_error_page(self, error_message):
"""エラー画面の生成"""
return f"""
<html>
<body>
<h1>エラー</h1>
<p>{error_message}</p>
</body>
</html>
"""
# 使用例
def setup_application():
"""アプリケーションの初期化"""
# 依存関係の注入
user_repository = UserRepository()
user_service = UserService(user_repository)
user_controller = UserController(user_service)
return user_controller

より詳細なレイヤー構造

5層アーキテクチャ

より大規模なアプリケーションでは、さらに細かくレイヤーを分けることがあります。

class FiveLayerArchitecture:
"""5層アーキテクチャの説明"""
def __init__(self):
self.layers = {
"presentation_layer": {
"name": "プレゼンテーション層",
"description": "ユーザーインターフェース",
"components": ["Controllers", "Views", "DTOs"],
"example_files": ["user_controller.py", "user_view.html"]
},
"application_layer": {
"name": "アプリケーション層",
"description": "アプリケーション固有の処理調整",
"components": ["Application Services", "Commands", "Queries"],
"example_files": ["user_application_service.py", "register_user_command.py"]
},
"domain_layer": {
"name": "ドメイン層",
"description": "ビジネスルールとエンティティ",
"components": ["Entities", "Value Objects", "Domain Services"],
"example_files": ["user_entity.py", "email_value_object.py"]
},
"infrastructure_layer": {
"name": "インフラストラクチャ層",
"description": "外部システムとの接続",
"components": ["Repositories", "External APIs", "Email Services"],
"example_files": ["user_repository.py", "email_service.py"]
},
"database_layer": {
"name": "データベース層",
"description": "データの永続化",
"components": ["Database", "Migrations", "Schemas"],
"example_files": ["001_create_users_table.sql", "database.py"]
}
}
def show_dependency_direction(self):
"""依存関係の方向を示す"""
dependencies = {
"rule": "上位層は下位層に依存するが、下位層は上位層に依存しない",
"correct_dependencies": [
"Presentation → Application",
"Application → Domain",
"Infrastructure → Domain",
"Database ← Infrastructure"
],
"forbidden_dependencies": [
"Domain → Application",
"Domain → Infrastructure",
"Application → Presentation"
]
}
return dependencies

ドメイン駆動設計(DDD)でのレイヤー

class DDDLayerStructure:
"""ドメイン駆動設計でのレイヤー構造"""
def __init__(self):
self.ddd_layers = {
"user_interface": {
"description": "ユーザーインターフェース層",
"responsibilities": [
"HTTPリクエストの処理",
"レスポンスの生成",
"認証・認可",
"入力値の検証"
],
"example_code": """
class UserController:
def __init__(self, user_application_service):
self.user_service = user_application_service
def register_user(self, request):
command = RegisterUserCommand(
name=request.json['name'],
email=request.json['email']
)
try:
result = self.user_service.register_user(command)
return {'success': True, 'user_id': result.user_id}
except DomainException as e:
return {'success': False, 'error': str(e)}
"""
},
"application": {
"description": "アプリケーション層",
"responsibilities": [
"ユースケースの調整",
"トランザクション管理",
"ドメインサービスの呼び出し",
"外部サービスとの連携"
],
"example_code": """
class UserApplicationService:
def __init__(self, user_repository, email_service):
self.user_repository = user_repository
self.email_service = email_service
@transaction
def register_user(self, command):
# ドメインオブジェクトの生成
user = User.create(
name=command.name,
email=Email(command.email)
)
# 重複チェック
if self.user_repository.exists_by_email(user.email):
raise DuplicateEmailException()
# 保存
self.user_repository.save(user)
# 副作用の実行
self.email_service.send_welcome_email(user)
return RegisterUserResult(user.id)
"""
},
"domain": {
"description": "ドメイン層",
"responsibilities": [
"ビジネスルールの実装",
"エンティティの管理",
"ドメインイベントの発行",
"不変条件の維持"
],
"example_code": """
class User:
def __init__(self, user_id, name, email):
self.id = user_id
self.name = name
self.email = email
self.created_at = datetime.now()
@classmethod
def create(cls, name, email):
# ビジネスルールの適用
if len(name) < 2:
raise InvalidNameException("名前は2文字以上必要です")
user_id = UserId.generate()
user = cls(user_id, name, email)
# ドメインイベントの発行
user.add_domain_event(UserRegisteredEvent(user.id))
return user
def change_email(self, new_email):
# ビジネスルールチェック
if self.email == new_email:
return # 変更なし
old_email = self.email
self.email = new_email
# ドメインイベント発行
self.add_domain_event(EmailChangedEvent(self.id, old_email, new_email))
class Email:
def __init__(self, value):
if '@' not in value:
raise InvalidEmailException("メールアドレスの形式が正しくありません")
self.value = value
def __eq__(self, other):
return isinstance(other, Email) and self.value == other.value
"""
},
"infrastructure": {
"description": "インフラストラクチャ層",
"responsibilities": [
"データベースアクセス",
"外部API呼び出し",
"ファイルシステムアクセス",
"メール送信"
],
"example_code": """
class SqlUserRepository:
def __init__(self, database):
self.db = database
def save(self, user):
query = '''
INSERT INTO users (id, name, email, created_at)
VALUES (?, ?, ?, ?)
'''
self.db.execute(query, (
str(user.id),
user.name,
user.email.value,
user.created_at
))
def find_by_id(self, user_id):
query = 'SELECT * FROM users WHERE id = ?'
row = self.db.query_one(query, (str(user_id),))
if row:
return User(
user_id=UserId(row['id']),
name=row['name'],
email=Email(row['email'])
)
return None
def exists_by_email(self, email):
query = 'SELECT COUNT(*) FROM users WHERE email = ?'
count = self.db.query_scalar(query, (email.value,))
return count > 0
"""
}
}

レイヤー間の通信方法

データの受け渡し

レイヤー間でデータをやり取りする際のベストプラクティスです。

class LayerCommunication:
"""レイヤー間の通信方法"""
def __init__(self):
self.communication_patterns = {
"dto_pattern": {
"name": "DTO(Data Transfer Object)パターン",
"purpose": "レイヤー間でのデータ転送",
"example": """
# プレゼンテーション層からアプリケーション層へ
class CreateUserRequest:
def __init__(self, name, email, age):
self.name = name
self.email = email
self.age = age
# アプリケーション層からプレゼンテーション層へ
class UserResponse:
def __init__(self, user_id, name, email, created_at):
self.user_id = user_id
self.name = name
self.email = email
self.created_at = created_at
"""
},
"command_pattern": {
"name": "コマンドパターン",
"purpose": "操作の実行要求",
"example": """
class RegisterUserCommand:
def __init__(self, name, email):
self.name = name
self.email = email
self.timestamp = datetime.now()
class UserCommandHandler:
def handle(self, command):
if isinstance(command, RegisterUserCommand):
return self.register_user(command)
"""
},
"query_pattern": {
"name": "クエリパターン",
"purpose": "データの取得要求",
"example": """
class GetUserQuery:
def __init__(self, user_id):
self.user_id = user_id
class GetUsersQuery:
def __init__(self, page=1, limit=20, filter_email=None):
self.page = page
self.limit = limit
self.filter_email = filter_email
class UserQueryHandler:
def handle(self, query):
if isinstance(query, GetUserQuery):
return self.get_user_by_id(query.user_id)
elif isinstance(query, GetUsersQuery):
return self.get_users_with_pagination(query)
"""
}
}
def demonstrate_layer_communication(self):
"""レイヤー間通信の実例"""
example = """
# 1. プレゼンテーション層:リクエスト受信
def create_user_endpoint(request):
# HTTPリクエストからDTOを作成
create_request = CreateUserRequest(
name=request.json['name'],
email=request.json['email'],
age=request.json['age']
)
# アプリケーション層に処理を委譲
try:
user_response = user_application_service.create_user(create_request)
return {
'status': 'success',
'data': {
'user_id': user_response.user_id,
'name': user_response.name,
'email': user_response.email
}
}
except ValidationError as e:
return {'status': 'error', 'message': str(e)}
# 2. アプリケーション層:ビジネス処理の調整
class UserApplicationService:
def create_user(self, create_request):
# ドメイン層でビジネスロジック実行
user = User.create(
name=create_request.name,
email=create_request.email,
age=create_request.age
)
# インフラ層でデータ永続化
saved_user = self.user_repository.save(user)
# DTOに変換して返却
return UserResponse(
user_id=saved_user.id,
name=saved_user.name,
email=saved_user.email,
created_at=saved_user.created_at
)
# 3. ドメイン層:ビジネスルール適用
class User:
@classmethod
def create(cls, name, email, age):
# バリデーション(ビジネスルール)
if age < 0 or age > 120:
raise ValidationError("年齢は0-120の範囲で入力してください")
if len(name.strip()) < 2:
raise ValidationError("名前は2文字以上で入力してください")
return cls(
id=cls.generate_id(),
name=name.strip(),
email=email.lower(),
age=age,
created_at=datetime.now()
)
# 4. インフラ層:データ永続化
class UserRepository:
def save(self, user):
# データベースに保存
query = '''
INSERT INTO users (id, name, email, age, created_at)
VALUES (?, ?, ?, ?, ?)
'''
self.db.execute(query, (
user.id, user.name, user.email, user.age, user.created_at
))
return user
"""
return example

実践的なレイヤー設計

ディレクトリ構造の例

class ProjectStructureExamples:
"""プロジェクト構造の例"""
def __init__(self):
self.structures = {
"simple_3layer": {
"description": "シンプルな3層構造",
"structure": """
project/
├── controllers/ # プレゼンテーション層
│ ├── user_controller.py
│ └── order_controller.py
├── services/ # ビジネス層
│ ├── user_service.py
│ └── order_service.py
├── repositories/ # データ層
│ ├── user_repository.py
│ └── order_repository.py
├── models/ # データモデル
│ ├── user.py
│ └── order.py
└── main.py # アプリケーション起動
"""
},
"ddd_structure": {
"description": "ドメイン駆動設計の構造",
"structure": """
project/
├── presentation/ # プレゼンテーション層
│ ├── controllers/
│ │ ├── user_controller.py
│ │ └── order_controller.py
│ └── dtos/
│ ├── user_dto.py
│ └── order_dto.py
├── application/ # アプリケーション層
│ ├── services/
│ │ ├── user_application_service.py
│ │ └── order_application_service.py
│ ├── commands/
│ │ ├── create_user_command.py
│ │ └── place_order_command.py
│ └── queries/
│ ├── get_user_query.py
│ └── get_orders_query.py
├── domain/ # ドメイン層
│ ├── entities/
│ │ ├── user.py
│ │ └── order.py
│ ├── value_objects/
│ │ ├── email.py
│ │ └── money.py
│ ├── services/
│ │ └── user_domain_service.py
│ └── repositories/ # インターフェース
│ ├── user_repository.py
│ └── order_repository.py
├── infrastructure/ # インフラ層
│ ├── persistence/
│ │ ├── sql_user_repository.py
│ │ └── sql_order_repository.py
│ ├── external/
│ │ └── email_service.py
│ └── database/
│ └── database.py
└── main.py
"""
}
}
def get_naming_conventions(self):
"""命名規則のガイドライン"""
conventions = {
"controllers": {
"pattern": "[Entity]Controller",
"examples": ["UserController", "OrderController"],
"responsibilities": ["HTTPリクエスト処理", "レスポンス生成"]
},
"services": {
"pattern": "[Entity]Service または [UseCase]Service",
"examples": ["UserService", "OrderProcessingService"],
"responsibilities": ["ビジネスロジック", "複数エンティティの調整"]
},
"repositories": {
"pattern": "[Entity]Repository",
"examples": ["UserRepository", "OrderRepository"],
"responsibilities": ["データ永続化", "データ取得"]
},
"entities": {
"pattern": "[Entity]",
"examples": ["User", "Order", "Product"],
"responsibilities": ["ビジネスデータの表現", "不変条件の維持"]
}
}
return conventions

テストにおけるレイヤー活用

class LayeredTesting:
"""レイヤー化されたアプリケーションのテスト戦略"""
def __init__(self):
self.testing_strategies = {
"unit_tests": {
"target": "各層の個別クラス・メソッド",
"isolation": "他の層に依存しない",
"example": """
# ドメイン層のユニットテスト
class TestUser:
def test_create_user_with_valid_data(self):
# 正常なユーザー作成
user = User.create(
name="田中太郎",
email="tanaka@example.com",
age=25
)
assert user.name == "田中太郎"
assert user.email == "tanaka@example.com"
assert user.age == 25
def test_create_user_with_invalid_age(self):
# 無効な年齢でのエラー
with pytest.raises(ValidationError):
User.create(
name="田中太郎",
email="tanaka@example.com",
age=-1
)
"""
},
"integration_tests": {
"target": "複数層の連携",
"isolation": "外部システムはモック化",
"example": """
# アプリケーション層の統合テスト
class TestUserApplicationService:
def setup_method(self):
# モックリポジトリを使用
self.mock_repository = Mock(spec=UserRepository)
self.user_service = UserApplicationService(self.mock_repository)
def test_register_user_success(self):
# 正常な登録処理
command = RegisterUserCommand("田中太郎", "tanaka@example.com")
# リポジトリの戻り値を設定
self.mock_repository.exists_by_email.return_value = False
self.mock_repository.save.return_value = Mock(id="user-123")
# テスト実行
result = self.user_service.register_user(command)
# 検証
assert result.user_id == "user-123"
self.mock_repository.save.assert_called_once()
"""
},
"end_to_end_tests": {
"target": "全層を通したシナリオ",
"isolation": "実際のシステム構成",
"example": """
# エンドツーエンドテスト
class TestUserRegistrationFlow:
def test_complete_user_registration(self):
# 実際のHTTPリクエストを送信
response = requests.post('http://localhost:8000/users', json={
'name': '田中太郎',
'email': 'tanaka@example.com',
'age': 25
})
# レスポンス確認
assert response.status_code == 201
data = response.json()
assert data['status'] == 'success'
assert 'user_id' in data['data']
# データベース確認
user = db.query_one(
"SELECT * FROM users WHERE email = ?",
("tanaka@example.com",)
)
assert user is not None
assert user['name'] == '田中太郎'
"""
}
}

よくある間違いと対策

アンチパターンの例

class LayerAntiPatterns:
"""レイヤー設計でよくある間違い"""
def __init__(self):
self.anti_patterns = {
"anemic_domain": {
"name": "貧血ドメインモデル",
"description": "ドメインクラスにロジックがなく、データのみ",
"problem": """
# ❌ 悪い例:ロジックがないドメインクラス
class User:
def __init__(self):
self.id = None
self.name = None
self.email = None
self.age = None
# ゲッター・セッターのみ
def set_name(self, name):
self.name = name
def get_name(self):
return self.name
# ビジネスロジックがサービス層に集中
class UserService:
def register_user(self, user_data):
# バリデーション
if len(user_data['name']) < 2:
raise ValueError("名前は2文字以上")
# ユーザー作成
user = User()
user.set_name(user_data['name'])
user.set_email(user_data['email'])
# 保存
return self.repository.save(user)
""",
"solution": """
# ✅ 改善例:ドメインロジックを持つクラス
class User:
def __init__(self, name, email, age):
self.id = self.generate_id()
self.name = self.validate_and_set_name(name)
self.email = self.validate_and_set_email(email)
self.age = self.validate_and_set_age(age)
def validate_and_set_name(self, name):
if len(name.strip()) < 2:
raise ValueError("名前は2文字以上必要です")
return name.strip()
def validate_and_set_email(self, email):
if '@' not in email:
raise ValueError("正しいメールアドレスを入力してください")
return email.lower()
def change_email(self, new_email):
old_email = self.email
self.email = self.validate_and_set_email(new_email)
# ドメインイベントの発行なども可能
return EmailChangedEvent(self.id, old_email, new_email)
"""
},
"layer_skipping": {
"name": "レイヤー飛び越し",
"description": "中間層を飛び越した直接アクセス",
"problem": """
# ❌ 悪い例:プレゼンテーション層からデータ層に直接アクセス
class UserController:
def __init__(self, user_repository):
self.user_repository = user_repository # 直接リポジトリに依存
def register_user(self, request):
name = request.get('name')
email = request.get('email')
# ビジネスロジックがコントローラーに混在
if len(name) < 2:
return {'error': '名前は2文字以上'}
# 直接リポジトリを呼び出し
user = self.user_repository.create_user(name, email)
return {'user_id': user.id}
""",
"solution": """
# ✅ 改善例:適切な層順序での依存
class UserController:
def __init__(self, user_service):
self.user_service = user_service # サービス層に依存
def register_user(self, request):
name = request.get('name')
email = request.get('email')
try:
# ビジネス層に処理を委譲
user = self.user_service.register_user(name, email)
return {'user_id': user.id}
except ValidationError as e:
return {'error': str(e)}
"""
},
"fat_controller": {
"name": "太ったコントローラー",
"description": "コントローラーにビジネスロジックが集中",
"problem": """
# ❌ 悪い例:すべてがコントローラーに集中
class OrderController:
def place_order(self, request):
# 複雑なビジネスロジックがコントローラーに
user_id = request.get('user_id')
items = request.get('items')
# 在庫チェック
for item in items:
stock = self.inventory_service.get_stock(item['product_id'])
if stock < item['quantity']:
return {'error': f'在庫不足: {item["product_id"]}'}
# 価格計算
total = 0
for item in items:
price = self.product_service.get_price(item['product_id'])
total += price * item['quantity']
# 割引適用
user = self.user_service.get_user(user_id)
if user.is_premium:
total *= 0.9
# 注文作成
order = self.order_repository.create_order(user_id, items, total)
# 在庫減少
for item in items:
self.inventory_service.decrease_stock(
item['product_id'],
item['quantity']
)
return {'order_id': order.id}
""",
"solution": """
# ✅ 改善例:ビジネスロジックをサービス層に移動
class OrderController:
def __init__(self, order_service):
self.order_service = order_service
def place_order(self, request):
user_id = request.get('user_id')
items = request.get('items')
try:
# ビジネスロジックはサービス層に委譲
order = self.order_service.place_order(user_id, items)
return {'order_id': order.id}
except InsufficientStockError as e:
return {'error': f'在庫不足: {e.product_id}'}
except InvalidOrderError as e:
return {'error': str(e)}
"""
}
}

まとめ

プログラミングにおけるレイヤー(層)の概念は、複雑なシステムを整理し、保守しやすいコードを書くための重要な考え方です。

適切にレイヤーを分けることで、コードの見通しがよくなり、変更や拡張が容易になります。

最初は3層アーキテクチャから始めて、プロジェクトの規模や複雑さに応じて、より詳細なレイヤー構造を検討してみてください。

レイヤーの概念を理解し、実践することで、より良いソフトウェア設計ができるようになるでしょう。

関連記事