プログラミングできなくてもブラウザで簡単にAPIを作成できるOSSのHeadless CMS「Strapi」の機能と使い方
モダンなWEBサイト制作・WEBシステム開発では、いわゆるJamstackと呼ばれるアーキテクチャを採用することが増えています。
このようなアーキテクチャを採用する場合はFirebaseのようなmBaaSを利用したり、自身でAPIを開発したり、データを永続的に保存するための方法が必要です。
APIを開発する場合、LaravelやCakePHPなどのフレームワークを利用して開発することも可能ですが、少なくない工数が発生します。
Strapiはオープンソースで開発されているHeadless CMSで、初期設定さえエンジニアが行えば誰でも管理画面を通じてGUIでAPIを作成できます。
この記事ではStrapiのインストールと基本的な使い方について紹介します。
Headless CMSとは
ユーザーに表示するための画面がないCMSをHeadless CMSといいます。
WordPressなどのCMSでは、サイトへの訪問者にはテーマで設定したページデザインで表示されますが、Headless CMSはユーザーに表示するためのページデザインは提供しません。コンテンツの管理およびコンテンツのAPIだけを提供します。
画面がないと不便と思う方もいらっしゃいますが、管理しているコンテンツをWEBだけでなくスマホアプリやデスクトップアプリなどでも表示したい場合、最初からStrapiのようなHeadless CMSで管理することで、コンテンツを一元的に管理でき、API開発にかかる工数も削減できるメリットがあります。
コードを記述せずにデータの構造を定義するだけでAPIを作成できるので、プロトタイピングやモックアップの作成、DXにおけるノーコード・ローコード開発にも向いています。
Strapiとは
オープンソースで開発されているNode.js製のHeadless CMSです。
次のようなことができます。
- コンテンツの管理
- 役割ごとに権限を設定
- APIの提供
- プラグインによる機能の拡張
- CMSのカスタマイズ
インストール方法
それでは早速インストール方法を説明します。
公式ガイドではいくつかの方法が紹介されていますが、環境によってはエラーが発生する場合があるため、この記事では別の方法でインストールします。
前提
この記事では次のソフトウェアが事前にインストールされている前提で説明します。
ソフトウェア | バージョン |
---|---|
Node.js | 14.x |
npm | 6.x |
yarn | 1.22.x |
strapi
コマンドをインストール
以下のコマンドでグローバルにstrapi
コマンドをインストールします。
yarn global add strapi
Strapiプロジェクトを作成
以下のコマンドでStrapiプロジェクトを作成します。
strapi new --no-run --dbclient=mysql --dbhost=localhost --dbport=3306 --dbname=database --dbusername=root --dbpassword=password strapi
※データベースの接続情報はconfig/database.js
に保存されます。このファイルはデフォルトではバージョン管理の対象に含まれるため、上記コマンドを実行する際に実際の接続情報を指定しないことをおすすめます。
実行が完了すると、次のようなメッセージが表示されます。
Creating a new Strapi application at /var/www/playground/strapi. Creating a project from the database CLI arguments. Creating files. Dependencies installed successfully. Your application was created at /var/www/playground/strapi. Available commands in your project: yarn develop Start Strapi in watch mode. yarn start Start Strapi without watch mode. yarn build Build Strapi admin panel. yarn strapi Display all available commands. You can start by doing: cd /var/www/playground/strapi yarn develop
環境変数を設定する
データベースの接続情報や公開URLなどは環境(開発環境/ステージング環境/本番環境)などによって変わることが多いです。
Strapiではそのような場合に設定を簡単に変更できるように、.env
による環境変数の設定に対応しています。
環境変数を設定するには、プロジェクトのルートディレクトリに移動し、.env.example
をコピーして.env
ファイルを作成します。
cd ./strapi
cp .env.example .env
作成した.env
ファイルを編集し、次のように変数を設定します。
HOST=0.0.0.0 PORT=1337 DATABASE_HOST=mysql DATABASE_PORT=3306 DATABASE_NAME=strapi DATABASE_USERNAME=root DATABASE_PASSWORD=root PUBLIC_URL=http://strapi.playground.test IS_PROXIED=true
※データベースの接続情報や公開URLなどは適宜ご自身の環境にあわせて変更してください
その他、環境変数で設定可能な値と内容についてはドキュメントをご確認ください。
Strapiを起動する
以上でStrapiを起動する準備ができましたので、次のコマンドで起動してみます。
yarn develop
※本番環境でStrapiを起動する場合はyarn start
コマンドを実行します。
ブラウザでhttp://localhost:1337にアクセスすると、welcomeページが表示されます。
welcomeページのガイドに従って最初のユーザーを作成します。
基本的な操作
コンテンツタイプを作成する
WordPressにおける投稿タイプのように、管理するコンテンツのタイプを作成します。
ダッシュボードではこのような画面が表示されます。
メニューから「Content-Types Builder」 を選択します。
「Content-Types Builder」ではコンテンツタイプを管理できます。
「Create new collection type」を選択します。
コレクションの情報を入力するモーダルウィンドウが表示されます。
基本設定
Display name
コンテンツタイプの表示名を入力します。英語で複数形で入力するのをおすすめします。
例: 管理するコンテンツが本であればbooks
を入力します。
高度な設定
Draft/publish system
下書き機能を利用する場合、ONにします。
Collection name
システム内で利用するコンテンツタイプの識別子です。APIのURIとデータベースにテーブル名に影響します。
「Display name」を英語で複数形で入力している場合、何も入力しなくても問題ありません。
各項目を入力して、「続ける」をクリックします。
コレクションのフィールドを入力するモーダルウィンドウが表示されます。
「Text」を選択してみます。
基本設定
Name
フィールド名を入力します。
Types
フィールドに入力する内容が短い文字列の場合は「Short text」、長い文字列の場合は「Long text」を選択します。
255文字以内なら「Short text」、255文字より多ければ「Long text」がおすすめです。
高度な設定
- 入力形式
- 必須
- 最小
- 最大
など、追加のフィールド情報を指定できます。
「Add another field」をクリックして、同様に「Rich text」で本文を入力するフィールドも追加します。
追加したら、「終了」をクリックします。
フィールドを追加したら、「保存」をクリックします。
コンテンツタイプを追加するとStrapiが再起動します。
少し待って画面を更新すると、作成したコンテンツタイプがメニューに表示されます。
コンテンツを作成する
メニューをクリックして、「Postsを追加」をクリックします。
各フィールドを入力し、「保存」をクリックします。
保存すると、右上の「Publish」ボタンが有効になります。
「Publish」をクリックすると作成したPostが公開されます。
ロールと権限を設定する
コンテンツタイプを追加したら、アクセス権を設定する必要があります。
メニューから[設定 > ロールと権限]を選択し、「Public」の右側のえんぴつのアイコンをクリックします。
Postsのアクションにすべてチェックを入れ、「Save」をクリックします。
APIを確認
http://localhost:1337/postsにアクセスすると、作成したPostsのデータがJSONで取得できていることがわかります。
[ { "id": 2, "title": "タイトル", "content": "本文.........本文本文", "published_at": "2021-02-04T06:41:43.000Z", "created_at": "2021-02-04T06:41:37.000Z", "updated_at": "2021-02-04T06:41:43.000Z" } ]
※ブラウザに表示されるJSONは整形はされません、見やすくするために執筆時に整形しています。
基本的な操作方法は以上です。
まとめ
オープンソースのHeadless CMS「Strapi」について紹介しました。
標準でインストールされているプラグインを利用することでwebhookの設定も可能なため、Laravelなどのフレームワークと組み合わせれば様々な機能が実現できます。
APIの開発が必要になった場合はぜひ利用を検討してみてください。
Herokuにアプリケーションをデプロイする方法(Laravel編)
開発したアプリケーションをインターネットに公開する際に、VPSやAWSのEC2を利用できます。
しかし、VPSやEC2などのサービスは基本的にサーバの管理を自身で行わなければいけません。
サーバ管理ではディスク容量に十分な空きスペースがあるか、CPUやメモリなどのリソースに余裕があるかなど、様々なメトリクス(指標)を把握・管理しなければいけないため、インフラが得意でなかったりアプリケーションの開発に集中したい場合などには時間をかけられない・かけたくない時もあります。
Herokuではインフラの管理はすべてマネージド(Herokuが管理してくれる)ので、サーバを管理する必要がなくなります。
この記事ではLaravelアプリケーションをHerokuにデプロイする方法について説明します。
Herokuとは
Herokuはアプリケーションを実行するための環境を用意してくれるプラットフォームで、サーバの管理の他、アドオンを追加することでAWS S3やデータベースサーバを追加することもできます。
またビルドパックと呼ばれるビルド設定を追加したり、自身でビルドスクリプトを記述することでPHPやNode.js、Javaなど様々な言語のアプリケーションをデプロイできます。
Herokuを使ってみる
※アプリケーションは既に作成済みの前提です。この記事では新しいLaravelプロジェクトでアプリケーションをデプロイします。
※アカウントは登録済の前提です。アカウントがない場合は次のページから登録できます。
Herokuの操作は管理画面からもできますが、CLI(コマンドラインインターフェース)も提供されています。
この記事ではCLIからの操作を説明します。
Heroku CLIをインストールする
次のページのガイドに従って、Heroku CLIのインストールおよびheroku login
コマンドまで実行します。
アプリケーションを作成する
次のコマンドでアプリケーションを作成できます。
heroku apps:create
上記コマンドを実行すると、アプリケーション名(例: arcane-gorge-56836)が表示されます。
他のコマンドを実行する際に指定するので、アプリケーション名を控えておきます。
もしアプリケーション名がわからなくなった場合はheroku apps
コマンドを実行するか、管理画面から確認できます。
ビルドパックを追加する
Laravelのアプリケーションを実行するにはサーバにPHPをインストールしたり、Composerで管理している依存パッケージをインストールしたりする必要があります。
heroku/php
ビルドパックを追加すると、上記のようなPHPアプリケーションを実行する環境を作成する処理を自動的に実施します。
ビルドパックを追加するには、次のコマンドを実行します。
heroku buildpacks:add -a arcane-gorge-56836 heroku/php
※-a
オプションは作成時に出力されたアプリケーション名を指定します。
Procfileを追加する
Herokuではいくつかのプロセスを実行することができます。
アプリケーションをWEBで公開する際にはweb
プロセスを実行する際のコマンドを指定する必要があります。
プロセスを実行する際のコマンドを指定するには、プロジェクトのルートディレクトリ(Laravelであればartisan
ファイルと同じディレクトリ)に次のようなProcfile
を作成します。
web: $(composer config bin-dir)/heroku-php-apache2 public
このようにweb
プロセスを指定すると、public
ディレクトリをドキュメントルートとしてApacheのプロセスが起動されます。
public/.htaccess
に相当するNginxの設定ファイルを追加すれば、Nginxでweb
プロセスを起動することもできます。
環境変数を設定する
Laravelではデータベースの接続情報やログの出力先などを.env
で設定できます。
Herokuの場合.env
ではなくHerokuの環境変数を利用して設定するのがデファクトスタンダードです。
Herokuで環境変数を設定するには、次のコマンドを実行します。
heroku config:set -a arcane-gorge-56836 \ APP_NAME=サンプルアプリケーション \ APP_ENV=production \ APP_KEY=base64:xxxxxxx \ APP_DEBUG=false \ APP_URL=https://arcane-gorge-56836.herokuapp.com/ \ LOG_CHANNEL=stderr \ LOG_LEVEL=error
アプリケーションをデプロイする
Herokuにアプリケーションをデプロイするには、GitでアプリケーションコードをHerokuのリポジトリにプッシュします。
git push heroku master
リモートリポジトリがない場合は次のコマンドでリモートリポジトリを追加します。
git remote add heroku https://git.heroku.com/arcane-gorge-56836.git
アプリケーションを確認する
次のコマンドを実行すると、ブラウザでアプリケーションを開きます。
heroku apps:open -a arcane-gorge-56836
以上でHerokuにLaravelのアプリケーションをデプロイできます。
Herokuでファイルシステムを使う場合の注意
Herokuではデプロイするたびに新しいコンテナが作成されるため、サーバ上に書き込んだファイルは永続化されません。
つまり、ユーザーがアップロードした画像等のファイルやアプリケーションログなどをファイルシステムに書き込むと、データが消失します。
Herokuにアプリケーションをデプロイする場合はログ出力先を標準出力に変更したり、S3にファイルをアップロードしたり、RedisやMemcachedなどにキャッシュを保存するなどファイルシステムを使わないように注意する必要があります。
設計と開発の原則
WEBサイト制作・WEBシステム開発で設計をせずにコードを作成してしまうと、仕様の変更に追従できなかったり影響範囲がわからず保守できない、もしくは不具合の多いWEBサイト・WEBシステムになってしまうことがあります。
しかし、設計・開発にもベストプラクティスが存在します。
ベストプラクティスに従うことで、仕様の変更に柔軟に対応できる保守性の高いWEBサイト・WEBシステムをつくることができます。
この記事では、コードを作成する際に意識すべきとよく言われる代表的な原則について紹介します。
SOLID
SOLIDとはオブジェクト指向プログラミングでソフトウェアを設計・開発する際に守るべき原則です。
以下の原則の頭文字を取って、SOLIDと呼ばれています。
- Single responsibility principle(単一責任の原則)
- Open–closed principle(開放閉鎖の原則)
- Liskov substitution principle(リスコフの置換原則)
- Interface segregation principle(インターフェイス分離の原則)
- Dependency inversion principle(依存性逆転の原則)
それぞれの詳細について説明します。
Single responsibility principle(単一責任の原則)
Single responsibility principle(単一責任の原則)は、ひとつのクラスに複数に責任を負わせてはいけないという原則です。
NGの例
<?php class Post { /** * Postの内容をHTMLのtableタグで出力する */ public function outputHtml() { // 処理... } /** * Postをデータベースに保存する */ public function save() { // 処理... } }
この例ではPost
クラスにHTMLを出力する責任とデータベースを操作する責任があります。
ひとつのクラスに複数の責任を負わせると、コードの複雑性が上がりプログラムを修正する際に影響範囲が読みづらくなります。
OKの例
<?php class PostHelper { /** * Postの内容をHTMLのtableタグで出力する */ public function outputHtml(Post $post) { // 処理... } } class PostModel { /** * Postをデータベースに保存する */ public function save() { // 処理... } }
このように、ひとつのクラスはひとつの責任を持つような設計にすることで、コードの見通しが良くなり影響範囲を少なくできます。
Open–closed principle(開放閉鎖の原則)
あるクラスに対して、機能を追加する度に処理を変更する必要がないような設計にするべきという原則です。
NGの例
<?php class Notifier { /** * Slackで通知を送信する */ public function notifyBySlack() { // 処理... } /** * メールで通知を送信する */ public function notifyByEmail() { // 処理... } /** * Chatworkで通知を送信する */ public function notifyByChatwork() { // 処理... } } function sendNotification ($channel) { $notifier = new Notifier(); switch ($channel) { case 'slack': $notifier->notifyBySlack(); break; case 'email': $notifier->notifyByEmail(); break; case 'chatwork': $notifier->notifyByChatwork(); break; default: // 想定していないchannelを指定された場合 } }
この例ではLINEやDiscordなど通知先を増やしたい場合にswitch
のcase
を都度追加しなければいけません。
OKの例
<?php interface NotifierInterface { /** * 通知を送信する */ public function notify(); } class SlackNotifier implements NotifierInterface { public function notify() { // Slackに通知を送信する処理 } } class EmailNotifier implements NotifierInterface { public function notify() { // Slackに通知を送信する処理 } } class ChatworkNotifier implements NotifierInterface { public function notify() { // Slackに通知を送信する処理 } } function sendNotification ($notifier) { $notifier->notify(); }
sendNotification
関数をNotifierInterface
を実装したクラスのインスタンスを受け取るように変更することで、通知先が増える度にsendNotification
関数の処理を修正しなくても良くなります。
Liskov substitution principle(リスコフの置換原則)
同じinterface
を実装したり、class
を継承したりしている場合、各クラスでの振る舞い(処理内容)が同じになっているべきという原則です。
NGの例
<?php interface NotifierInterface { /** * 通知を送信する */ public function notify(); } class SlackNotifier implements NotifierInterface { public function notify($message = '') { $response = Slack::send($message); if ($response->status === 'OK') { return '1'; } else { return '0'; } } } class EmailNotifier implements NotifierInterface { public function notify($message = '') { $response = Email::send($message); if ($response->status === 'OK') { return true; } else { return false; } } } function sendNotification ($notifier) { $success = $notifier->notify(); if ($success) { Session::message('通知を送信しました'); } else { Session::message('通知を送信できませんでした'); } }
この例ではNotifierInterface
を実装しているSlackNotifier
クラスとEmailNotifier
で返り値の型が異なっています。
呼び出し元が振る舞いや返り値の違いを考慮する必要があると、クラスを呼び出す際に都度内部の仕様まで確認する必要があるため、効率が悪くバグの発生にもつながります。
OKの例
<?php interface NotifierInterface { /** * 通知を送信する */ public function notify(): bool; } class SlackNotifier implements NotifierInterface { public function notify($message = '') { $response = Slack::send($message); if ($response->status === 'OK') { return true; } else { return false; } } } class EmailNotifier implements NotifierInterface { public function notify($message = '') { $response = Email::send($message); if ($response->status === 'OK') { return true; } else { return false; } } } function sendNotification ($notifier) { $success = $notifier->notify(); if ($success) { Session::message('通知を送信しました'); } else { Session::message('通知を送信できませんでした'); } }
NotifierInterface
でnotify
メソッドの返り値を明示的にbool
であることを指定すると、実装クラスに返り値を強制できる(異なる型を返却するとエラーになる)ため、sendNotification
関数の処理ではnotify
メソッドの返り値をbool
である前提で扱えるようになります。
Interface segregation principle(インターフェイス分離の原則)
Interface
で実装を定義する際に、実装クラス側で必要のないメソッドの定義を強制してはいけないという原則です。
NGの例
<?php interface NotifierInterface { /** * 通知を送信する */ public function notify(): bool; /** * SlackのAPIキーを取得する */ protected function getSlackApiKey(): string; } class SlackNotifier implements NotifierInterface { public function notify($message = '') { $apiKey = $this->getSlackApiKey(); // 処理... } protected function getSlackApiKey() { // APIキーを取得する } } class EmailNotifier implements NotifierInterface { public function notify($message = '') { $response = Email::send($message); if ($response->status === 'OK') { return true; } else { return false; } } protected function getSlackApiKey() { // 何もしない } } function sendNotification ($notifier) { $notifier->notify(); }
EmailNotifier
クラスではgetSlackApiKey
メソッドは使わないので定義する必要はありませんが、interface
でメソッドの定義を強制しているため、不要なメソッドを定義しています。
OKの例
<?php interface NotifierInterface { /** * 通知を送信する */ public function notify(): bool; } class SlackNotifier implements NotifierInterface { public function notify($message = '') { $apiKey = $this->getSlackApiKey(); // 処理... } protected function getSlackApiKey() { // APIキーを取得する } } class EmailNotifier implements NotifierInterface { public function notify($message = '') { $response = Email::send($message); if ($response->status === 'OK') { return true; } else { return false; } } } function sendNotification ($notifier) { $notifier->notify(); }
この例ではgetSlackApiKey
メソッドはSlackNotifier
クラスの内部でしか利用しない、つまり共通化する必要がないので、SlackNotifier
クラスの内部で定義するだけで十分でしょう。
Dependency inversion principle(依存性逆転の原則)
あるクラスにメソッドが定義されていることを、クラス定義ではなくInterface
で担保するべきという原則です。
NGの例
<?php class SlackNotifier { public function notify() { // 処理... } } function sendNotification (SlackNotifier $notifier) { $notifier->notify(); }
この例ではsendNotification
関数がSlackNotifier
クラスのインスタンスに依存しており、別の通知先に送信するにはsendEmailNotification
のような関数を追加しなければいけません。
OKの例
<?php interface NotifierInterface { /** * 通知を送信する */ public function notify(): bool; } class SlackNotifier implements NotifierInterface { public function notify() { // 処理... } } function sendNotification (NotifierInterface $notifier) { $notifier->notify(); }
SlackNotifier
などのような通知先ごとのクラスにnotify
メソッドがあることをNotifierInterface
に担保させることで、sendNotification
関数はNotifierInterface
を実装したインスタンスとして$notifier
を受け取れるようになり、通知先の違いを意識せずにnotify
メソッドを呼び出すことができます。
KISSの原則
Keep it simple, stupid.
の略です。DeepLで翻訳すると
シンプルにしとけよ、アホ。
になります。
ソフトウェアを設計する際には何事もシンプルにするべきという原則です。
プログラムで例を示しますが、システムアーキテクトなど広い範囲に当てはまる考え方です。
NGの例
<?php class Post { public static function getAll($user = null, $id = null) { // 処理... } } $posts = Post::getAll();
この例ではgetAll
メソッドにユーザーを指定するとそのユーザーと紐づくPost
データ、さらにIDを指定すると特定のIDを持つPost
データを取得できることを想定しています。
しかし、例えばユーザーは指定せずにIDだけを指定したい、といったユースケースが出てきてしまうと、途端にこの処理は複雑化します。
OKの例
<?php <?php class Post { public static function getAll() { // 処理... } public static function getByUser() { // 処理... } public static function getById() { // 処理... } } $posts = Post::getAll();
実際にはクエリビルダーなどを利用することで更にシンプルに記述できますが、このようにメソッドを分けることでNGの例よりも各メソッドの処理をシンプルにできます。
YAGNI
「You ain't gonna need it」の略で、(機能などが)必要になるまでは実装すべきでないという原則です。
前述のSOLIDで示した例で言えば、様々な通知チャンネルを作成できるようにNotifierInterface
を実装したSlackNotifier
クラスやEmailNotifier
クラスを定義しました。
もし仕様として、様々な通知チャンネルを作成する必要があると明確に決まっている場合は示したような実装をするとSOLID的には良いのですが、80%不要にも関わらず将来的に必要になるかもしれない、といった理由でChatworkNotifier
クラスやDiscordNotifier
クラスなどを作成してしまうと、使わなかった場合作成にかかった時間は無駄になってしまいます。
また、コードが増えれば増えるほどバグが生まれる可能性も上がります。
拡張性を意識することは重要ですが、過度に拡張性を重視してしまうと必要以上に時間がかかったり、無用のバグを生み出したりします。
本当に拡張性が必要な機能かどうか、検討が必要です。
DRY
「Don't repeat yourself」の略で、同じコードを繰り返し書いてはいけないという原則です。
同じコードを何度も記述すると、例えば仕様に変更が発生した際に多くの修正が発生するかもしれません。
同じ処理であればクラスのメソッドや関数に処理を記述し、メソッド・関数を呼び出すように共通化することで何度も同じ記述をせずに済みます。
ただし、同じ記述であってもSOLIDの原則(特に単一責任の原則)を満たさない形で共通化してはいけません。
無闇に共通化すると、ひとつの修正で思わぬ部分に影響が出ることもあるので、同じ処理でもコンテキストが異なる場合はあえて共通化しない方が保守しやすいプログラムになる場合もあります。
GOF Design Patterns
GOFとは
オブジェクト指向における再利用のためのデザインパターンという書籍を執筆した4人の著者をよく「Gang of Four」と呼びます。
GOF Design Patternsとは
上記の書籍で紹介されている、オブジェクト指向プログラミングの設計パターンのことです。
オブジェクト指向プログラミングでよく採用される設計のパターンが紹介されていて、問題に直面した時にこの書籍で紹介されているパターンを知っていれば時間をかけずに良い設計で解決できるようになります。
domain-driven design(ドメイン駆動設計)
Eric Evans氏のDomain-Driven Design: Tackling Complexity in the Heart of Softwareで紹介されたソフトウェアの設計手法です。よくDDDと略されます。
かなり内容が濃く、人によって理解が若干異なる場合があります。
ドメイン駆動設計 - Wikipediaによれば、次のような要素から表現されるそうです。
ドメイン駆動設計では、ドメインモデルを表現する要素として、下記のものを挙げている。
- エンティティ (参照オブジェクト): ドメインモデル内のオブジェクトであり、その属性によってではなく、連続性と識別性によって定義される。
- 値オブジェクト: 事物の特性を記述するオブジェクトである。特に識別する情報はなく、通例、読み出し専用のオブジェクトであり、Flyweight パターンを用いて共有できる。
- サービス: 操作がオブジェクトに属さない場合に、問題の自然な解決策として、操作をサービスとして実現することができる。サービスの概念は、GRASPにおいて"純粋人工物"と呼ばれるものである。
- リポジトリ:ドメインオブジェクトを取得するメソッドは、記憶域の実装を簡単に切り替えられるようにするため、専門のリポジトリオブジェクトに処理を委譲するべきである。
- ファクトリー : ドメインオブジェクトを生成するメソッドは、実装を簡単に切り替えられるようにするため、専門のファクトリーオブジェクトに処理を委譲するべきである。
Test-Driven Development(テスト駆動開発)
プログラムを作成する際に、プログラムよりも先にテストコードを作成し、テストコードが正常に終了するようにプログラムを作成し、その後にプログラムを修正していく開発手法をテスト駆動開発と言います。英語の頭文字を取って、TDDとも呼ばれます。
テスト駆動開発のメリット
テスト駆動開発では実装よりも前にテストコードを書くため、実装前に仕様を設計してテストコードとして具体的に定義できます。テストコードで明確な仕様を定義できるため、実装漏れを防ぐのに役立ちます。また、一般的なテスト駆動開発ではモジュール単位でテストコードを作成するため、疎結合なモジュール設計になりやすいです。
テスト駆動開発のデメリット
プロトタイピングのような開発の場合、機能の開発後に大幅な仕様変更が発生することがあります。仕様が大きく変わる場合作成したテストコードがすぐに使えなくなるため、テスト駆動開発には向いていません。また、テストコードを実行する環境をテストの度にビルドするような設計の場合、規模の大きいモノリシックなシステムではビルドに数時間以上かかることがあり、修正の度に数時間の待ち時間が発生し効率が悪くなる場合もあります。
まとめ
この記事では最低限知っておくべき設計、開発の原則を紹介しました。
これらの原則を意識して設計・開発することで、継続的に改善していくことが可能なWEBサイト・WEBシステムを開発しやすくなります。
【Google Chrome】デベロッパーツールの使い方(基本編)
HTML, CSS, JavaScriptをコーディングする際に、ちょっとしたケアレスミスで意図したように表示されなかったり実行されなかったりすることがあります。
そのような場合にHTML, CSS, JavaScriptだけを読んで問題を解決するのは少し効率が悪いかもしれません。
コーディングした内容が実際にどのようにブラウザで処理されるか確認をするためにデベロッパーツールを利用することで、効率よくコーディングを進めることができます。
この記事ではGoogle Chromeのデベロッパーツールの基本的な使い方について紹介します。
各機能の詳細は量が多いので別の記事で紹介しています。
- 【Google Chrome】デベロッパーツールの使い方(デバイスツールバー編)
- 【Google Chrome】デベロッパーツールの使い方(Elements編)
- 【Google Chrome】デベロッパーツールの使い方(Console編)
- 【Google Chrome】デベロッパーツールの使い方(Sources編)
- 【Google Chrome】デベロッパーツールの使い方(Network編)
- 【Google Chrome】デベロッパーツールの使い方(Performance編)
- 【Google Chrome】デベロッパーツールの使い方(Memory編)
- 【Google Chrome】デベロッパーツールの使い方(Application編)
- 【Google Chrome】デベロッパーツールの使い方(Security編)
- 【Google Chrome】デベロッパーツールの使い方(Lighthouse編)
- 【Google Chrome】デベロッパーツールの使い方(Settings編)
デベロッパーツールとは
デベロッパーツールはブラウザに標準で付属している、開発者向けのデバッグツールです。
HTML, CSSの確認やDOM構造の確認、JavaScriptのデバッグからWEBページの改善点の提案まで、様々な機能が含まれています。
この記事ではGoogle Chromeのデベロッパーツールを紹介しますが、ほとんどの機能は他のブラウザのデベロッパーツールでも利用できます。
デベロッパーツールを使うには
デベロッパーツールは、ブラウザのメニューから[表示 > 開発 / 管理 > デベロッパーツール]を選択するか、次のショートカットキーで表示できます。
OS | ショートカットキー |
---|---|
Windows10 | F12 |
macOS | ⌘ + ⌥ + I |
デベロッパーツールのレイアウト
①要素を選択する
Elementsタブでフォーカスする要素を選択できます。
②デバイスツールバーを表示する
後述のデバイスツールバーを表示できます。
③タブ
クリックすると表示するタブを切り替えられます。
④エラーと警告
Consoleに表示されるエラーと警告の件数が表示されます。
クリックするとConsoleタブが表示されます。
⑤設定
デベロッパーツールの設定を変更できます。
⑥デベロッパーツールメニュー
クリックすると次のようなメニューが表示されます。
Dock side
クリックするとデベロッパーツールの表示位置を変更できます。
左から順に、別ウィンドウ・左側・下・右側に表示されます。
Show console drawer
クリックすると以下のようにコンテンツエリア下部にConsoleドロワーが表示されます。
機能はConsoleタブと同等です。
Search
読み込んだリソースの中から指定のキーワードで検索を実行できます。
Run command
様々なコマンドを実行できます。
macOSでは[⌘ + ⇧ + P]Windows10では[Ctrl + Shift + P]で実行することもでき、コマンドでChromeの設定などを変更できるので左記のショートカットキーと組み合わせて利用することで操作を効率化できます。
Open file
読み込んだリソースの中から指定のキーワードを含むファイルをSourcesタブに表示できます。
More tools
その他のツールが表示されます。
⑦デベロッパーツールを閉じる
クリックするとデベロッパーツールを閉じます。
⑧コンテンツエリア
選択したタブの内容が表示されるエリアです。
デバイスツールバー
【Google Chrome】デベロッパーツールの使い方(デバイスツールバー編)で紹介しています。
Elements
【Google Chrome】デベロッパーツールの使い方(Elements編)で紹介しています。
Console
【Google Chrome】デベロッパーツールの使い方(Console編)で紹介しています。
Sources
【Google Chrome】デベロッパーツールの使い方(Sources編)で紹介しています。
Network
【Google Chrome】デベロッパーツールの使い方(Network編)で紹介しています。
Performance
【Google Chrome】デベロッパーツールの使い方(Performance編)で紹介しています。
Memory
【Google Chrome】デベロッパーツールの使い方(Memory編)で紹介しています。
Application
【Google Chrome】デベロッパーツールの使い方(Application編)で紹介しています。
Security
【Google Chrome】デベロッパーツールの使い方(Security編)で紹介しています。
Lighthouse
【Google Chrome】デベロッパーツールの使い方(Lighthouse編)で紹介しています。
Settings
【Google Chrome】デベロッパーツールの使い方(Settings編)で紹介しています。
さいごに
デベロッパーツールは非常に多機能ですべてを使いこなすには時間をかけて学ぶ必要があるかもしれません。
作業内容によって利用する機能は異なりますが、HTM, CSS, JavaScriptのコーディングをする場合次の機能をよく利用します。
- デバイスツールバー
- Elements
- Console
- Sources
- Network
- Lighthouse
こちらの機能だけでも使えるようになると、効率よくコーディングを進めることができる思うのでぜひお試しください。