🙌
【初心者】ソフトウェアアーキテクチャパターン
状況
- エンジニアに転職して3ヶ月が経ちました。がむしゃらにとにかくタスクをこなしてきて漸く少しコードまみれの生活にも慣れてきました。
- 一方で、もう3ヶ月も経ってしまったことに焦りを感じています。早く仕事として使えるようになるために基礎をぶっ飛ばしてとにかく実践に触れてきたため、あまり体系的に自分の中に知識が詰まっていないことに愕然としています。
- 例えば「Active Record」なんか完全に知ってるフリしてます。今後は実践を捌きながらも基礎をガンガン学んでいきたいと思います。
内容
Active Recordを調べようと思ったら、そもそも「ソフトウェアアーキテクチャパターン」を理解しないといけないことが分かりましたのでそこから整理してみます。
ソフトウェアアーキテクチャパターンとは?
- ソフトウェアアーキテクチャパターンは、アプリケーションの設計を整理し、保守性や拡張性を高めるためのパターン = システムをどのように構築するかの設計の枠組み
- 家を建てるときに「間取り」を決めるようなもので、どのようにデータを流し、処理を分けるかのルールを決める
Ruby on Rails は MVC(Model-View-Controller)パターン を採用している
これが最も基本的なアーキテクチャパターン
1. MVC(Model-View-Controller)パターン
概要
MVCは、以下の3つの役割に分けることでコードを整理しやすくするアーキテクチャパターンのこと
役割 | 説明 |
---|---|
Model | データの管理(DBとのやり取り、ビジネスロジック) |
View | ユーザーに見える画面(HTML、CSS、JavaScript) |
Controller | ユーザーのリクエストを処理し、ModelとViewをつなぐ |
実際の流れ(ブログ記事の表示を例に)
- ユーザーが
/articles/1
にアクセス -
Controller (
ArticlesController
) がリクエストを受け取る -
Model (
Article
クラス) から記事データを取得 -
View (
show.html.erb
) でデータを整形し、HTMLを生成 - ユーザーのブラウザにページが表示される
実装例(Rails)
# app/controllers/articles_controller.rb
class ArticlesController < ApplicationController
def show
@article = Article.find(params[:id]) # Modelに問い合わせ
end
end
<!-- app/views/articles/show.html.erb -->
<h1><%= @article.title %></h1>
<p><%= @article.body %></p>
MVCパターンを使うと、データの管理、画面の表示、リクエストの処理が明確に分かれる
他の言語の場合
- Django(Python) も同じMVCパターン(DjangoではMTVと呼ばれるが、概念は同じ)
- Spring(Java) でもMVCを採用
- Express(Node.js) でも、ルーティング・モデル・ビューを分けることでMVC的に実装可能
(応用編)2. レイヤードアーキテクチャ
概要
MVCの拡張版で、アプリケーションをさらに細かい層(レイヤー)に分けるパターン
レイヤー | 役割 |
---|---|
Presentation | ViewとControllerを含み、ユーザーとのやり取りを担当 |
Application | アプリのビジネスロジック(ユースケースごとの処理) |
Domain | ビジネスルールやエンティティの管理 |
Infrastructure | データベースや外部APIの管理 |
Railsにおける実践
RailsのMVCに加えて、以下のようにServiceクラスやRepositoryクラスを作ると、レイヤードアーキテクチャに近づけられる
実装例(Serviceクラスを導入)
# app/services/article_service.rb
class ArticleService
def self.find_article(id)
Article.find(id)
end
end
# app/controllers/articles_controller.rb
class ArticlesController < ApplicationController
def show
@article = ArticleService.find_article(params[:id]) # Serviceを経由
end
end
こうすることで、Controllerが直接Modelを扱わず、ビジネスロジックを切り離せる ようになる
他の言語の場合
- Spring(Java) はこの構造が標準的
- NestJS(Node.js) もこのような構造を推奨
- Laravel(PHP) でもサービス層を作ることで類似の構造を実装可能
(発展編)3. クリーンアーキテクチャ
概要
レイヤードアーキテクチャをさらに厳密にし、依存関係を内側から外側に制限する考え方
レイヤー | 役割 |
---|---|
Entities(エンティティ) | ドメインルールを持つ純粋なオブジェクト |
Use Cases(ユースケース) | アプリのビジネスルールを表現 |
Interface Adapters(インターフェース) | ControllerやView、DB操作など |
Frameworks & Drivers(外部技術) | Rails, DB, Webフレームワーク |
Railsにおける実践
クリーンアーキテクチャを意識する場合、以下のような構成になる
# app/domain/article.rb
class Article
attr_reader :title, :body
def initialize(title, body)
@title = title
@body = body
end
end
# app/repositories/article_repository.rb
class ArticleRepository
def self.find(id)
ArticleRecord.find(id) # ActiveRecordのモデルを操作
end
end
# app/use_cases/article_use_case.rb
class ArticleUseCase
def self.get_article(id)
article = ArticleRepository.find(id)
Article.new(article.title, article.body)
end
end
# app/controllers/articles_controller.rb
class ArticlesController < ApplicationController
def show
@article = ArticleUseCase.get_article(params[:id])
end
end
こうすることで、Rails(外部技術)に依存せずに、ビジネスロジック(ユースケース)を独立させられる
他の言語の場合
- Spring Boot(Java) ではクリーンアーキテクチャを意識した構成が一般的
- NestJS(Node.js) でもクリーンアーキテクチャを採用しやすい
- Go(Golang) でもこの考え方がよく使われる
所見
- まじで全然理解してませんでした。この活動は続けたいと思います
- でも、やはり「コントローラは薄いのが至高」という考えが根っこにあるということは一緒
- 思ったより長くなってしまったので、Avtive Recordは次の記事にまとめることにします
次の記事
Discussion