はじめに
BASE株式会社でシニアエンジニアを務めているプログラミングをするパンダ(@Panda_Program)と申します。本連載はバックエンドの開発者向けに特化したフロントエンド入門です。
対象読者
本連載の対象読者はオブジェクト指向プログラミングの基礎を理解しており、フロントエンド開発に興味があるバックエンドエンジニアの方です。バックエンド開発で主流であるオブジェクト指向プログラミングと比較しながらフロントエンドの考え方を理解することで、スムーズにフロントエンド開発を始められることを目的としています。
フロントエンド開発とバックエンド開発の違い
フロントエンド開発とバックエンド開発の違いを全て語ると紙面が足りないため、本連載ではプログラミングスタイルの比較に焦点を絞ります。
ここでいう、フロントエンド開発はReactなどのUIライブラリを使ったコンポーネントでSPA(Single Page Application)のWebサイトを作る開発を指します。また、バックエンド開発はオブジェクト指向プログラミングでフロントエンドからコールされるAPIサーバーを実装することに限定します。
なお、フロントエンドはJavaScriptを中心に解説を進めてHTMLやCSSの説明は省略します。使用言語はTypeScriptとReactです。
オブジェクト指向とコンポーネント指向
まず、オブジェクト指向とコンポーネント指向の違いを簡単に説明します。
オブジェクト指向はグラフ構造である
オブジェクト指向プログラミングの特徴は、特定のデータとそのデータに関する操作をクラスで表現することです。クラスが持つデータはプロパティと呼ばれ、このプロパティをクラス外から操作できないようにすることが良いとされています(カプセル化)。
クラスは型として表現されますが、値を持たせてクラスをインスタンス化することでオブジェクトを生成し、複数のオブジェクト同士が協調して処理をするのがオブジェクト指向のアプリケーションです。
オブジェクト指向では、オブジェクト同士が互いに関係しあっています。このオブジェクト同士のネットワークを「オブジェクトグラフ」と呼びます[1]。
![Ray.Di オブジェクトグラフの視覚化より、オブジェクトグラフの例](http://cz-cdn.shoeisha.jp/static/images/article/20648/20648_001.png)
オブジェクト指向プログラミングには他にも継承やインターフェース、ポリモーフィズムといった他の特徴もありますが本記事では説明を省略します。
オブジェクト指向のクラスの例としてブログの記事を表現する Article クラスを作ります。ArticleクラスはID(ArticleId)、タイトル(Title)、本文(Content)、著者(Author)、公開日(Date)を持ちます。タイトルと本文は編集可能ですが、それ以外の値は更新できないものとします。ここでは各プロパティのクラスなどを割愛して本記事の最後にコードの全文を掲載します。
// 記事クラス class Article { constructor( public readonly articleId: ArticleId, private title: Title, private content: Content, public readonly author: Author, private status: StatusValue, public readonly publishedAt: Date ) {} editTitle(newTitle: Title) { if (this.status === Status.Archived) { throw new Error('Archived な記事のタイトルは編集できません'); } this.title = newTitle; } getTitle(): Title { return this.title; } // 省略 }
このArticleクラスは、例えば記事を取得するGetArticleServiceや記事を公開するPublishArticleServiceといった別のオブジェクトから呼び出されます。サービス層のクラス(GetArticleService など)はドメイン層のクラス(Article)やインターフェース(ArticleRepositoryInterface)に依存します。そして ArticleRepositoryInterface もまた Article クラスに依存します。一つのクラスが複数のクラスやインターフェースに依存されることはよくあります。
オブジェクト指向では、このようにさまざまなオブジェクトがグラフ構造で互いに繋がっているのです。
フロントエンドはツリー構造である
オブジェクト指向のアプリケーションがグラフ構造である一方、フロントエンドのアプリケーションは基本的にツリー構造です。例えばHTMLはツリー構造のマークアップ言語です。
現代ではフロントエンドのアプリケーションを構築するために、ReactやVue.jsといったコンポーネント指向の宣言的なUIライブラリが使われます。これらのUIライブラリはUI全体をツリーとして捉えています。実際、Reactの公式ドキュメントに「UIをツリーとして理解する」という記事があります。
![](http://cz-cdn.shoeisha.jp/static/images/article/20648/20648_002.png)
一般的に、アプリケーションが大規模なものに成長すると、ページが増えてHTMLのツリー全体の管理が煩雑になってしまいます。そこで、ReactはこのHTMLのツリー構造をコンポーネントという小さな単位に分割して管理することで、再利用性や保守性を向上させてアプリケーションのスケーラビリティを担保するのです。各コンポーネントはUIツリーの一部を表現し、それらを組み合わせることでUI全体を構築します[2]。
先ほど記事クラスを紹介したように、React コンポーネントの例として記事コンポーネントを以下で定義します。
// 記事コンポーネント function Article() { return ( <article> <header> <h2>記事タイトル</h2> <p>著者: @Panda_Program(公開日: 2024/12/31)</p> </header> <p>本文です</p> </article> ); }
ReactコンポーネントはHTMLではなくJSXを返します。JSXとはJavaScript内でHTMLライクな構文を記述するための構文拡張です。このReactコンポーネントはブラウザで以下のHTMLとして描画されます。
<article> <header> <h2>記事タイトル</h2> <p>著者: @Panda_Program(公開日: 2024/12/31)</p> </header> <p>本文です</p> </article>
![](http://cz-cdn.shoeisha.jp/static/images/article/20648/20648_003.png)
この例だとコンポーネントが一つしかないため、ツリー構造であることがわかりづらいかもしれません。例えば、Article コンポーネントから以下のようにコンポーネントを切り出してみます。
function ArticleTitle() { return <h2>記事タイトル</h2>; } function ArticleHeader() { return ( <header> <ArticleTitle /> <p>著者: @Panda_Program(公開日: 2024/12/31)</p> </header> ); } function ArticleBody() { return <p>本文です</p>; } function Article() { return ( <article> <ArticleHeader /> <ArticleBody /> </article> ); }
コンポーネント同士の親子関係は以下のように表すことができます。
Article ├── ArticleBody └── ArticleHeader └── ArticleTitle
このようにReactコンポーネントはアプリケーションを構築する際にツリー構造を持ちます。
- [1]Qiita「アプリケーションはオブジェクトグラフ」に「オブジェクト指向のアプリケーションは相互に関係のある複雑なオブジェクト網を含んでいます。(中略)このオブジェクト網をオブジェクトグラフと呼びます。」という文があります。
- [2]ReactはコンポーネントからUIツリーを生成するだけです。描画のためには別のライブラリを使います。ReactコンポーネントをブラウザでDOMとして描画するためにはreact-domというライブラリが必要です。描画先をブラウザに限定しないのであれば、ネイティブアプリを作成するためのreact-nativeやターミナルで使うreact-terminalというライブラリとReactを組み合わせて使います。かつてはVRを描画するreact-360もありましたが、こちらの開発は終わってしまいました。