Slide 1

Slide 1 text

Active Record から考える 次世代の Ruby on Rails の方向性 Yuichi Goto (@_yasaichi) January 29,2021 @ 銀座 Rails #29

Slide 2

Slide 2 text

self.inspect Yuichi Goto(@_yasaichi) ピクスタ株式会社 執行役員 CTO 「パーフェクト Ruby on Rails【増補 改訂版】」 共著者(Part 5 担当) 2

Slide 3

Slide 3 text

[PR] ピクスタはクリエイティブプラットフォームを創る会社です 画像出典: https://pixta.co.jp/business 3

Slide 4

Slide 4 text

本発表の背景と目的 4

Slide 5

Slide 5 text

さかのぼること 2 年 2019 年 3 月に Railsdm というイベントで「Ruby on Rails の正体と向き 合い方 [1]」というタイトルで発表を行い、当時それなりの反響があった その後もいくつかの発表・エントリで引用していただいた(一部抜粋) 発表: Ruby (off|with) the Rails [2]、Fat Model の倒し方 [3] ブログエントリ: Smart UI パターンが再評価される世界 [4] 5

Slide 6

Slide 6 text

前回の発表後に起きたこと: フロントエンドの進化 1. Next.js の現在の主要機能が v9 で概ね実装され、React フレームワーク としての確固たる地位を築く(2019 年 7 月 [5]~ 2020 年 7 月 [6]) 2. Next.js と Prisma 2 をもとに作られた Rails インスパイアのフルスタック フレームワークである Blitz.js がリリースされる(2020 年 4 月 [7]) 3. JavaScript のフルスタックフレームワークで Rails を置き換えられるの ではないか、という機運が高まる(e.g. Frontend 領域を再定義する [8]) 6

Slide 7

Slide 7 text

本発表における問題意識 JavaScript のフルスタックフレームワークで Rails を置き換えられると仮定 したとき、次の問題があると考える。 Prisma 2 などの JavaScript の ORM で Rails の Active Record と 同等の開発生産性を実現しようとした場合の課題に関する議論が少ない その前提となる Active Record が果たす役割に関する議論も少ない 7

Slide 8

Slide 8 text

本発表の目的とアプローチ 目的: Rails の Active Record が果たす役割を明らかにする 明らかにした内容をもとに 次世代の Rails の方向性を考察する ことで、 未来の有益な議論に繋げる アプローチ: ソフトウェアアーキテクチャのパターンを起点とした考察 8

Slide 9

Slide 9 text

以降の構成 1. 第一部: Rails の Active Record の正体 2. 第二部: 次世代の Rails の方向性 3. まとめ 9

Slide 10

Slide 10 text

第一部: Rails の Active Record の正体 1. レイヤードアーキテクチャ 2. ドメインレイヤー以下のアーキテクチャ 3. Rails の Active Record が果たす役割 10

Slide 11

Slide 11 text

レイヤードアーキテクチャとは 「Pattern-Oriented Software Architecture,Volume 1,A System of Patterns [9]」(※)における定義は次の通り。 アプリケーションを適当数のレイヤーで構造化し、これらを積み重ねたもの あるレイヤーにおいて、その構成要素は同一抽象レベルで作業を行う あるレイヤーの提供するサービスは、隣接する下位レイヤーが提供する サービスを利用して実現される ※ 以下、POSA と呼ぶ 11

Slide 12

Slide 12 text

レイヤードアーキテクチャの概念図 各レイヤーはクラスや関数として 実装される 画像出典: POSA(p. 35) より著者作成 12

Slide 13

Slide 13 text

Web アプリケーションにおけるレイヤリング One of the most common ways to modularize an information-rich program is to separate it into three broad layers: presentation (UI), domain logic (aka business logic), and data access. So you often see web applications divided into . . . On the whole Ive found this to be an effective form of modularization for many applications and one that I regularly use and encourage. ― Martin Fowler (2015) [10] “ “ ※ 太字強調は引用者によるもの 13

Slide 14

Slide 14 text

Web アプリケーションを構成する主要なレイヤー Fowler 氏の著書「Patterns of Enterprise Application Architecture [11]」(※)では、次の 3 つのレイヤーが挙げられている。 プレゼンテーション: ユーザーからのコマンド(例: HTTP リクエスト)を 下位レイヤーの呼び出しへ変換、ユーザーへの情報の表示 ドメイン: 入力データの妥当性確認、入力・格納データにもとづく計算 データソース: データベース、メッセージングシステムなどとの通信 ※ 以下、PoEAA と呼ぶ 14

Slide 15

Slide 15 text

第一部: Rails の Active Record の正体 1. レイヤードアーキテクチャ 2. ドメインレイヤー以下のアーキテクチャ 3. Rails の Active Record が果たす役割 15

Slide 16

Slide 16 text

ドメインレイヤーのアーキテクチャパターン PoEAA で紹介されているパターンのうち、利用する言語・フレームワークに 関係なく採用できるものは次の通り。 トランザクションスクリプト: プレゼンテーションレイヤーからの 1 つの 要求を処理する手続き ドメインモデル: アプリケーションが対象とする問題領域(ドメイン)から 抽出された概念をオブジェクトとして定義したもの 16

Slide 17

Slide 17 text

ドメインレイヤーの分割とサービスレイヤー ドメインレイヤーはドメインモデルとその上位レイヤーの 2 つに分割される ことが多く、後者を PoEAA では「サービスレイヤー」と呼んでいる サービスレイヤーは複数のドメインモデルやデータソースを協調させて、 プレゼンテーションレイヤーからの要求に応える役割を担う 文脈によって同レイヤーを指す呼び名が変わるため注意が必要 (例: クリーンアーキテクチャの同心円の図では「ユースケース」と呼ぶ) 17

Slide 18

Slide 18 text

2 つのパターンの主な違い: ドメインの複雑化に伴う機能追加の労力の変化 トランザクションスクリプトは単純なドメイン では有効だが、複雑になると重複ロジックを 単に抽出した関数が増えて見通しが悪くなる 単純なドメインでドメインモデルを 利用しても設計が面倒なだけだが、 複雑になるとその労力が報われる 画像出典: PoEAA(p. 29) 18

Slide 19

Slide 19 text

データソースレイヤーのアーキテクチャパターン PoEAA において、データストアが RDB の場合に利用できるパターンとして 紹介されているものは次の通り。 (テーブル|行)データゲートウェイ: RDB 内の(テーブル|レコード)への 操作をカプセル化するオブジェクト アクティブレコード: ドメインロジックを実装した行データゲートウェイ データマッパー: ドメインモデルと RDB 内のレコードを相互変換するもの ※ Rails の Active Record との混同を避けるため、ここでは意図的に訳本のパターン名を用いている 19

Slide 20

Slide 20 text

2 つのレイヤーのアーキテクチャパターンの関係 ドメインとデータソースのアーキテクチャパターンは互いに独立ではなく、 次の組み合わせで利用されることが多い(理由は後述)。 A. トランザクションスクリプト + (テーブル|行)データゲートウェイ B. ドメインモデル + アクティブレコード C. ドメインモデル + データマッパー 以降の議論には関係しないため、 こちらの組み合わせは紹介に留める 20

Slide 21

Slide 21 text

各組み合わせの実装例 次の正常系のフローからなる「ニュースレター登録機能」を、前ページの組み 合わせ A,B で実装した例を示す。 1. ユーザーは、フォームにメールアドレスを入力して「登録」ボタンを押す 2. アプリケーションは、メールアドレスの形式が正しいことを確認する 3. アプリケーションは、メールアドレスとその存在確認用のトークンを DB に 記録して、ユーザーに確認メールを送信する 21

Slide 22

Slide 22 text

DB = Sequel.connect("connection_url") class SubscribeToNewsletter Result = Struct.new(:errors, :subscription_id, keyword_init: true) def self.call(email:) unless URI::MailTo::EMAIL_REGEXP.match?(email) return Result.new(errors: ["Email is invalid"]) end values = { email: email, confirmation_token: SecureRandom.uuid } DB.transaction do id = DB[:newsletter_subscriptions].insert(values) EmailConfirmationMailer.deliver(values) Result.new(subscription_id: id) end rescue StandardError Result.new(errors: ["Something went wrong"]) end end A. トランザクションスクリプト + テーブルデータゲートウェイ ドメインロジックは スクリプト内にべた書き 22

Slide 23

Slide 23 text

class SubscribeToNewsletterService Result = Struct.new(:errors, :subscription_id, keyword_init: true) def self.call(email:) unless URI::MailTo::EMAIL_REGEXP.match?(email) return Result.new(errors: ["Email is invalid"]) end subscription = NewsletterSubscription.new(email: email) subscription.set_confrimation_token NewsletterSubscription.transaction do subscription.save! EmailConfirmationMailer .deliver(subscription.slice(:email, :confirmation_token)) Result.new(subscription_id: subscription.id) end rescue StandardError Result.new(errors: ["Something went wrong"]) end end B. ドメインモデル + アクティブレコード with サービスレイヤー 23

Slide 24

Slide 24 text

第一部: Rails の Active Record の正体 1. レイヤードアーキテクチャ 2. ドメインレイヤー以下のアーキテクチャ 3. Rails の Active Record が果たす役割 24

Slide 25

Slide 25 text

Rails の Active Record とは MVC パターンを採用している Rails におけるモデルに相当するもので、 Rails を構成する gem の 1 つである activerecord にその実体がある 各アプリケーションでは、この gem が提供する ActiveRecord::Base という 基底クラスを継承して固有のモデルを定義する 名前からも明らかなように、この基底クラスは PoEAA のアクティブレコー ドの実装になっている [12] 25

Slide 26

Slide 26 text

PoEAA のアクティブレコードにはない機能 基底クラス ActiveRecord::Base は PoEAA のアクティブレコードにはない次の 代表的な機能を持っている。 バリデーション: データベース操作の実行前にモデルの状態を検証できる ようにするもの(例: ある属性が空でないかの確認) コールバック: データベース操作の実行前後に任意のコードを実行できる ようにするもの 設定したコードはデータベース操作と 同一のトランザクション内で実行される 26

Slide 27

Slide 27 text

class NewsletterSubscription < ActiveRecord::Base validates :email, format: { with: URI::MailTo::EMAIL_REGEXP } before_create :set_confrimation_token after_create :send_email_confirmation_instructions private def set_confrimation_token self[:confirmation_token] = SecureRandom.uuid end def send_email_confirmation_instructions EmailConfirmationMailer.deliver(slice(:email, :confirmation_token)) end end NewsletterSubscription.create(email: "[email protected]") 2 つの機能を利用すると「ニュースレター登録機能」がモデルで完結する 27

Slide 28

Slide 28 text

「ニュースレター登録機能」の各実装例のアーキテクチャ上の違い クラスとして実装されていた複数のレイヤーは Rails ではモデルとそのメソッドに対応する 28

Slide 29

Slide 29 text

Rails の Active Record が果たす役割 次の方法で ドメインレイヤー以下をモデルクラスだけで構築できるように して、コードの記述量を減らす ことで、高い開発生産性を実現している。 アクティブレコードを採用して、ドメインレイヤーとデータソースレイヤーを 1 つのクラスで実装できるようにした バリデーションとコールバックを導入して、サービスレイヤーのロジックを モデルクラスの DSL やインスタンスメソッドで実装できるようにした 29

Slide 30

Slide 30 text

コードの記述量を減らすその他のアプローチ コードの記述量を減らして開発生産性を向上させるために、Rails は次のアプ ローチを Active Record と併用している。 Convention Over Configuration: Rails の規約に従うと、アプリケー ションの設定に関するコードの多くを記述しなくてすむようにした リソースベースのルーティング: REST に則った URI 設計を行うと、多くの コードを自動生成できるようにした 30

Slide 31

Slide 31 text

Rails のアプローチの構造的な限界: 暗黙の 1:1 対応が崩れるとき プレゼンテーションレイヤーからのある要求に特化 したバリデーションとコールバックが問題となる 31

Slide 32

Slide 32 text

限界との向き合い方 データベースレベル: イベントエンティティ(※1)を見落としていないか 確認して、もしあれば対応するモデルに問題のロジックを移動する コードレベル(※2): 新たにサービスレイヤーを導入して、こちらに問題の ロジックを移動する アーキテクチャレベル(※2): ドメインを最初から小さくする、後から分割 して小さくすることで問題を発生させない プレゼンテーションレイヤーからの要求と イベントエンティティの生成は 1:1 対応 している場合が多く、問題になりにくい ※1、※2 詳しくはイミュータブルデータモデル [13]、Ruby on Rails の正体と向き合い方 [1]をそれぞれ参照のこと 32

Slide 33

Slide 33 text

第一部完 33

Slide 34

Slide 34 text

[PR] 会社で「texta.fm」という Podcast を運営しています この Podcast でピクスタの技術顧問である和田卓人 (@t_wada)さんと議論した内容が本発表の下敷きに なっています。改めて感謝申し上げます。 画像出典: https://anchor.fm/textafm 34

Slide 35

Slide 35 text

第二部: 次世代の Rails の方向性 1. 2 つの方向性 2. フロントエンドからのアプローチ 3. バックエンドからのアプローチ 35

Slide 36

Slide 36 text

フルスタックフレームワークのあるべき姿 この後の議論を展開するために、本発表ではフルスタックフレームワークの あるべき姿を次のように定義する。 定義: Web アプリケーションのあらゆる領域で、そのフレームワークを 利用した方が常に高い成果を得られるという状態を実現するもの Rails における高い成果の例: バックエンドの汎用的な機能をすぐに実装 できる、特に何もしなくても一定のセキュリティ対策が行われるなど 36

Slide 37

Slide 37 text

ここ 10 年でのあるべき姿の変化 いくつかの理由により(※)、Web アプリケーションの利用を通じて得られる ユーザー体験の重要性が年々高まっている これに伴い、ユーザーと Web アプリケーションの界面であるフロントエンド 領域が確立され、前ページの「あらゆる領域」に加わった 2021 年 5 月から Google の検索順位の決定にユーザー体験指標(Core Web Vitals)が導入予定のため [14]、直近ではより関心が高まっている Rails が登場したのは 2004 年であることに注意 ※ 例えば、ソフトウェアが企業の業務支援のための手段からビジネスそのものに変化したから、という理由が挙げられる 37

Slide 38

Slide 38 text

Rails の現状 バックエンドでの高い開発生産性を実現するための仕組みと比較すると、 ユーザー体験を向上させるための仕組みはあまり充実していない 例: Largest Contentful Paint(※)において改善余地のある事項 Turbolinks の実装の都合上、デフォルトでは全ての CSS ファイルが application.css に連結されて 内で読み込まれること Sprockets が画像に対してデフォルトでは何の最適化も行わないこと ※ Core Web Vitals の構成指標で、ユーザーがページ内の最も有意義なコンテンツをどのくらい早く見れるかを表す 38

Slide 39

Slide 39 text

差分を埋めるアプローチ = 次世代の Rails の方向性 1. フロントエンドからのアプローチ Next.js のような質の高いユーザー体験を実現するための仕組みの中で、 バックエンドを Rails と同等の生産性で開発できるようにする 2. バックエンドからのアプローチ Rails のバックエンドでの高い開発生産性を実現するための仕組みの中で、 Next.js などと同等の水準のユーザー体験を実現できるようにする 39

Slide 40

Slide 40 text

第二部: 次世代の Rails の方向性 1. 2 つの方向性 2. フロントエンドからのアプローチ 3. バックエンドからのアプローチ 40

Slide 41

Slide 41 text

重要な要素: Prisma v1 は任意のデータストアに GraphQL を被せるサーバーの実装だったが、 2020 年 6 月リリースの v2 [15] では単なる TypeScript の ORM となった 主な特長として、独自スキーマで定義したデータモデルをもとにした自動 型生成とマイグレーションの実行機能がある Blitz.js,RedwoodJS といった新興のフルスタックフレームワークの多くで 採用されているため、次世代の Rails を語る上で重要な要素である ※ 以降、バージョン番号なしで Prisma と表記した場合、 Prisma 2 のことを指すものとする 41

Slide 42

Slide 42 text

const prisma = new PrismaClient(); // Create const createdUser = await prisma.user.create({ data: { email: '[email protected]' }, }); // Read const user = await prisma.user.findUnique({ where: { id: createdUser.id } }); // Update const updatedUser = await prisma.user.update({ where: { id: user!.id }, data: { email: '[email protected]' }, }); // Delete await prisma.user.delete({ where: { id: updatedUser.id } }); Prisma におけるデータベース操作の例 各データベース操作はRDB内の テーブルに対応するオブジェクトの メソッド呼び出しに対応する 42

Slide 43

Slide 43 text

Prisma は PoEAA のどのパターンを実装しているか 公式ドキュメントでは、"Prisma is a new kind of Data Mapper ORM" と 述べられている [16] 前ページで示したように、Prisma は POJO(※)と RDB 内のレコードを 相互変換しているので、広義のデータマッパーと言えなくもない しかし、この POJO にドメインロジックは実装できない(レコードの表現で しかない)ため、テーブルデータゲートウェイの実装と言った方が正しい ※ Plain Old JavaScript Objectの略。素のJavaScriptオブジェクトのこと。 43

Slide 44

Slide 44 text

ドメインレイヤーのアーキテクチャ選定に働く重力 ドメインレイヤー以下をドメインモデル + Prisma で構築する場合、 Prisma の返す POJO のデータをドメインモデルに詰め直す必要がある 特にアプリケーションの実装初期段階では、ドメインモデルと RDB 内の テーブルが 1:1 対応することが多いため、この作業は手間なだけである 結果として、ドメインモデルを利用せずに ドメインレイヤー以下をトラン ザクションスクリプト + Prisma で構築する方向に重力が働く p. 21の理由のひとつがこちら 44

Slide 45

Slide 45 text

import { Ctx } from "blitz" import db from "db" import { hashPassword } from "app/auth/auth-utils" import { SignupInput, SignupInputType } from "app/auth/validations" export default async function signup(input: SignupInputType, { session }: Ctx) { // This throws an error if input is invalid const { email, password } = SignupInput.parse(input) const hashedPassword = await hashPassword(password) const user = await db.user.create({ data: { email: email.toLowerCase(), hashedPassword, role: "user" }, select: { id: true, name: true, email: true, role: true }, }) await session.create({ userId: user.id, roles: [user.role] }) return user } 実際にトランザクションスクリプト + Prisma に帰着した例(Blitz.js) 出典: blitz/examples/custom-server/app/auth/mutations/signup.ts [17] 45

Slide 46

Slide 46 text

Prisma を採用するフレームワークが抱える課題 Prisma を採用するフルスタックフレームワークがバックエンドで Rails と 同等の開発生産性を実現しようとしたとき、現時点では次の課題に直面する。 Rails の高い開発生産性を実現している仕組みは、アクティブレコードの 採用が前提であるため再現できない こと(別のアプローチが必要) ドメインレイヤーは自ずとトランザクションスクリプトを採用することになる ため、 ドメインが複雑になると開発生産性が急落する性質を持つ こと 46

Slide 47

Slide 47 text

Prisma 以外の ORM はどうか JavaScript には次のような著名なアクティブレコードの実装が存在するが、 TypeScript 周りで Prisma に劣るため、現時点では甲乙つけがたい。 Sequelize: 約 10 年の歴史を持つこともあり機能面では充実しているが、 TypeScript 対応が弱く、それなりの量の型宣言を書く必要がある [18] TypeORM: Decorator により Sequelize の問題が緩和されており、機能 面でも十分だが、多くの場面で Prisma よりも型安全性が低い [19] どちらもバリデーションと コールバック機能を持つ 47

Slide 48

Slide 48 text

Prisma の将来はどうか we re planning to over time (1) add more features on a Prisma level that help you express data-related business logic (e.g. extended validation rules) and (2) provide callbacks/hooks for you to make it easier to implement business logic . . . I strongly encourage you and everyone else to share your use cases and feature requests . . . as this helps us to prioritizing and designing upcoming features! ― Johannes Schickling (Founder of Prisma,2019) [20] “ “ ※ 太字強調は引用者によるもの 48

Slide 49

Slide 49 text

フロントエンドからのアプローチの成否 次のいずれかの展開により、 ドメインレイヤーでの開発生産性の問題が 解消されるかどうかが鍵になる のではないか。 Prisma またはフルスタックフレームワーク側が Prisma の返す POJO に ドメインロジックを実装する仕組みを提供する(≠ アクティブレコード化) アクティブレコードを実装する他の ORM の TypeScript 周りが改善される 現状のままでも問題ないとわかる、またはそう考える人が多数派になる 49

Slide 50

Slide 50 text

第二部: 次世代の Rails の方向性 1. 2 つの方向性 2. フロントエンドからのアプローチ 3. バックエンドからのアプローチ 50

Slide 51

Slide 51 text

重要な要素: Rails 7 次の DHH 氏の言動から、Rails 7 ではフロントエンドに大きな変更が加わる ことが予想されるため、ここではその方向性について考察する。 2020 年 12 月に SPA を構築するための新しいアプローチ「Hotwire」を 発表、同時に Rails 向けの実装である hotwire-rails を公開した [21] 2021 年 1 月に出演したある Podcast で、「Rails 7 では Hotwire を導入 してデフォルトで有効にしたい」という旨の発言をした [22] 51

Slide 52

Slide 52 text

フロントエンドでのもう 1 つの試み: 脱 Webpack Hotwire と並行した次の取り組みにより、DHH 氏は Rails での Webpack の 利用を必須ではなくそうとしている [23] [24]。 ブラウザの ES Modules サポートを前提に Import Maps(※)の shim を 利用して、JavaScript のビルドなしで hotwire-rails が動くようにする Tailwind CSS でスタイリングできるようにして、Tailwind CSS 自体以外の CSS のビルドをなくす(この実装が tailwindcss-rails ) 未使用クラスの除去は Sprockets で行う ※ import foo from "foo" をブラウザで実現する議論中の仕様。詳しくは WICG の GitHub [25] を参照のこと 52

Slide 53

Slide 53 text

背景にある DHH 氏の問題意識 次の発言から、 現代のフロントエンドは問題に対して解決策が必要以上に 複雑になっていることが多い と DHH 氏は感じているのではないか。 “You start super stupid simple and then you just pay as you go for the complexity that you use and no more.” [26] “I also agree that apps that don t want or need that [Webpack] shouldn t have to wrestle with something this complex.” [27] 53

Slide 54

Slide 54 text

バックエンドからのアプローチの成否 現時点では、Rails 7 において起こるだろうフロントエンドでの大きな変更は 開発生産性の向上が主な目的のため、次の事項が鍵になるのではないか。 DHH 氏がユーザー体験の向上に対して問題意識を持つ(現時点では優先 順位が低いだけで、既に問題意識がある可能性は大いにある) コミュニティ(※)側から、ユーザー体験の向上に関するフィードバックや プルリクエストを送っていく ※ 私と本日お集まりいただいた皆さんのことです! 54

Slide 55

Slide 55 text

第二部完 55

Slide 56

Slide 56 text

まとめ 56

Slide 57

Slide 57 text

第一部: Rails の Active Record の正体 Web アプリケーションは、プレゼンテーション、ドメイン、データソースの 3 レイヤーから構成されることが多い Rails の Active Record が果たす役割は、アクティブレコードの採用、 バリデーションとコールバックの導入によって、ドメインレイヤー以下を モデルクラスだけで構築できるようにすることである Active Record や CoC、リソースベースのルーティングによってコードの 記述量を減らすことで、Rails はその高い開発生産性を実現している 57

Slide 58

Slide 58 text

第二部: 次世代の Rails の方向性 フルスタックフレームワークのあるべき姿を実現するアプローチを次世代の Rails の方向性としたとき、そのアプローチと課題は次の通り。 1. フロントエンドからのアプローチ: JavaScript の ORM のアーキテクチャ などに起因するドメインレイヤーでの開発生産性の問題の解消が課題 2. バックエンドからのアプローチ: Rails 7 で起こるだろうフロントエンドでの 変更が現時点ではユーザー体験の向上が主な目的でないことが課題 58

Slide 59

Slide 59 text

ご清聴ありがとうございました 59

Slide 60

Slide 60 text

参考文献 60

Slide 61

Slide 61 text

参考文献 1 1. Yuichi Goto "Ruby on Rails の正体と向き合い方",URL: https://speakerdeck.com/yasaichi/what-is-ruby- on-rails-and-how-to-deal-with-it↩ 2. Shinpei Maruyama "Ruby (off|with) the Rails",URL: https://speakerdeck.com/shinpeim/ruby-off-with- the-rails↩ 3. toshimaru "Fat Model の倒し方",URL: https://speakerdeck.com/toshimaru/how-to-deal-with-fat- model↩ 4. Takafumi ONAKA "Smart UI パターンが再評価される世界",URL: https://onk.hatenablog.jp/entry/2020/11/11/024531↩ 5. Vercel,Inc. "Next.js 9",URL: https://nextjs.org/blog/next-9↩ 6. Vercel,Inc. "Next.js 9.5",URL: https://nextjs.org/blog/next-9-5↩ 7. Brandon Bayer " Announcing Blitz.js: Rails-like framework for full-stack React apps — built on Next.js". URL: https://dev.to/flybayer/announcing-blitz-js-rails-like-framework-for-full-stack-react-apps- built-on-next-js-g1o↩ 61

Slide 62

Slide 62 text

参考文献 2 8. mizchi "Frontend Study #1: 基調講演 - Frontend 領域を再定義する",URL: https://zenn.dev/mizchi/articles/c638f1b3b0cd239d3eea↩ 9. Frank Buschmann,Regine Meunier,Hans Rohnert,Peter Sommerlad,and Michael Stal (1996) Pattern- Oriented Software Architecture,Volume 1,A System of Patterns: Wiley.↩ 10. Martin Fowler "PresentationDomainDataLayering",URL: https://martinfowler.com/bliki/PresentationDomainDataLayering.html↩ 11. Martin Fowler (2002) Patterns of Enterprise Application Architecture: Addison-Wesley Professional.↩ 12. "Active Record – Object-relational mapping in Rails",URL: https://github.com/rails/rails/tree/6-1- stable/activerecord#label-Philosophy↩ 13. kawasima "イミュータブルデータモデル",URL: https://scrapbox.io/kawasima/イミュータブルデータモデル↩ 14. Jeffrey Jose "Timing for bringing page experience to Google Search",URL: https://developers.google.com/search/blog/2020/11/timing-for-page-experience↩ 62

Slide 63

Slide 63 text

参考文献 3 15. Nikolas Burk "Prisma 2.0: Confidence and productivity for your database",URL: https://www.prisma.io/blog/announcing-prisma-2-n0v98rzc8br1↩ 16. "Is Prisma an ORM?",URL: https://www.prisma.io/docs/concepts/overview/prisma-in-your-stack/is- prisma-an-orm↩ 17. "blitz/signup.ts at v0.29.3 · blitz-js/blitz",URL: https://github.com/blitz- js/blitz/blob/v0.29.3/examples/custom-server/app/auth/mutations/signup.ts↩ 18. "TypeScript - Manual | Sequelize",URL: https://sequelize.org/master/manual/typescript.html↩ 19. "Prisma vs TypeORM",URL: https://www.prisma.io/docs/concepts/more/comparisons/prisma-and- typeorm#type-safety↩ 20. "How will prisma2 handle business logic? · Issue #353 · prisma/specs",URL: https://github.com/prisma/specs/issues/353↩ 21. DHH on Twitter,December 23 2020,1:27 AM,URL: https://twitter.com/dhh/status/1341420143239450624↩ 63

Slide 64

Slide 64 text

参考文献 4 22. "Remote Ruby | Hotwire, Rails NEXT, and the DHH Stack™ with David Heinemeier Hansson",URL: https://share.transistor.fm/s/336e93f9↩ 23. DHH on Twitter,January 14 2021,11:18 PM,URL: https://twitter.com/dhh/status/1349722504483500041↩ 24. DHH on Twitter,Dec 26 2020,7:26 PM,URL: https://twitter.com/dhh/status/1342778751575347200↩ 25. "WICG/import-maps: How to control the behavior of JavaScript imports",URL: https://github.com/WICG/import-maps↩ 26. "Full Stack Radio | 151: DHH – Building HEY with Hotwire",URL: https://share.transistor.fm/s/152b6067↩ 27. "Webpacker presents a more difficult OOB experience for JS Sprinkles than Sprockets did - A May Of WTFs - Ruby on Rails Discussions",URL: https://discuss.rubyonrails.org/t/webpacker-presents-a-more- difficult-oob-experience-for-js-sprinkles-than-sprockets-did/75345/31↩ 64