DXエージェンシースパイスファクトリー株式会社、エンジニアのワンです。
スパイスファクトリーの
(新しいタブで開きます)はこちら。
この記事では、React 初心者の方に向けて、react hooks についての基本説明と、いくつかの hook の紹介をしていきます。
そもそも、 hook とは何でしょうか。
React 公式サイト(新しいタブで開きます)では、hooks について以下のように説明してあります。
フック (hook) は React 16.8 で追加された新機能です。state などの React の機能を、クラスを書かずに使えるようになります。
要は、hook は Reactの state やライフサイクルの機能などを、関数コンポーネント内に使用できるようにするための関数です。
React 公式ドキュメントでは、クラスコンポーネントより hook を用いる関数コンポーネントの方がおすすめだとされています。
なぜクラスコンポーネントではなく関数コンポーネントを使用した方が良いのでしょうか。
実際に両者のソースコードを比較していきましょう。
クラスは this を使用しています。 例えば this.setState などの特殊な状態処理メソッドを指します。
しかし、this は JavaScript の特別なキーワードであり、状況によって異なるものを参照するため、分かり辛い場合があります。
それに加えて、コードが多くなると更に複雑になります。
以下はクラスコンポーネントの簡単な例です。
import React from 'react';
class HelloComponent extends React.Component {
constructor(props) {
super(props);
this.state = { name: '' };
this.handleChange = this.handleChange.bind(this);
};
handleChange(event) {
this.setState({ name: event.target.value });
};
render() {
const { name } = this.state
return (
<div>
<input value={name} onChange={this.handleChange} />
<p>Hello {name}</p>
</div>
);
};
};
次のコードは、上と同じコンポーネントを関数コンポーネントとして書いたものです。
import React, { useState } from 'react';
const HelloComponent: React.FC = () => {
const [name, setName] = useState('');
const handleChange = (event) => {
setName(event.target.value)
};
return (
<div>
<input value={name} onChange={handleChange} />
<p>Hello {name}</p>
</div>
);
};
こちらは this を使用せず、 useState という hook を使って name の値を管理しています。
クラスコンポーネントと比べてコードの量が少なく、読みやすい印象です。
hook でロジックをカプセル化できるので、UIとロジックの分離が容易になります。
また、一度定義した hook は、関数コンポーネント内と他の hook 内でも使いまわせます。
hook には2つのルールがあります。
hook の使用にあたって、まずこれらを理解しておく必要があります。
尚、呼び出しの順番に関しては、if 条件やループ、ネストした関数の中に hook を入れることもできませんのでその点もご注意ください。
続いて、React が公式で出している hook について紹介します。
ここでは最もよく使われるという理由から useState と useEffect をピックアップしてご説明します。
useState と useEffect 以外にも、useContext、useRef、useCallback などの hook があるので、詳しく知りたい方はこちらの記事(新しいタブで開きます)を参照してください。
https://ja.reactjs.org/docs/react-api.html#hooks
import { useState } from 'react';
const [state, setState] = useState(initialState);
useState は state の値とその値を更新するためにセッター関数 setState を返します。
ステート管理のため、クラスコンポーネントのthis.stateとthis.setState()の代わりに使えます。
import { useEffect } from 'react';
useEffect(() => {
// 実行処理
}, []));
useEffect は、クラスコンポーネントの componentDidMount、componentDidUpdate、componentWillUnmount のメソッドの代わりに使えます。
1つ目の引数として定義した関数の実行が2つ目の引数の値によって変わります。イメージとしては以下です。
その他にも便利な hook はたくさんあります。
react hook form はフォームを検証するのに役立つライブラリです。
hook の形にしたメソッドで使用されます。
以下は react-hook-form を使った簡単な例です。
import { useForm } from 'react-hook-form';
const HelloFormComponent = () => {
const { register, handleSubmit, formState: { errors } } = useForm();
const onSubmit = (data) => console.log('Hello: ' + data.name);
return (
<form onSubmit={handleSubmit(onSubmit)}>
<input defaultValue="" {...register("name")} placeholder="名前" />
{errors.exampleRequired && <span>必須項目です</span>}
<input type="submit" />
</form>
);
};
また、独自の hook を定義することもできます。
こちら(新しいタブで開きます)は custom hook が集まっているレポジトリです。
https://github.com/streamich/react-use
これまで私自身が作成した hook についても1つピックアップしてご紹介します。
この hook は isScrollAtTop と isScrollAtBottom を返します。scroll の位置が一番上もしくは一番下にあるかどうかを教えてくれます。
import { useCallback, useEffect, useState } from 'react';
import throttle from 'lodash/throttle';
const fps = 12;
const useIsScrollAtTopBottom = (
targetDom: HTMLDivElement | (Window & typeof globalThis) = window,
scrollTopThreshold = 0
) => {
const [isScrollAtTop, setIsScrollAtTop] = useState(false);
const [isScrollAtBottom, setIsScrollAtBottom] = useState(false);
const target = targetDom;
const handleScroll = useCallback(() => {
const scrollPosition =
'pageYOffset' in target ? target.pageYOffset : target.scrollTop;
const scrollHeight =
'document' in target
? target.document.documentElement.scrollHeight
: target.scrollHeight;
const containerHeight =
'innerHeight' in target ? target.innerHeight : target.clientHeight;
const maxScrollTop = scrollHeight - containerHeight;
if (scrollPosition = maxScrollTop) {
setIsScrollAtBottom(true);
} else {
setIsScrollAtTop(false);
setIsScrollAtBottom(false);
}
}, [target, scrollTopThreshold]);
const throttledScroll = throttle(handleScroll, 1000 / fps);
useEffect(() => {
targetDom.addEventListener('scroll', throttledScroll);
return () => targetDom.removeEventListener('scroll', throttledScroll);
}, [handleScroll]);
return { isScrollAtTop, isScrollAtBottom };
};
以下は実際の使い方です。
isScrollAtBottom の値が true になったら、loadNextPage() で次のページを取得する処理を実行します。
そうすると、無限スクロールを実現することができます。
const { isScrollAtBottom } = useIsScrollAtTopBottom();
useEffect(() => {
if (isScrollAtBottom) {
loadNextPage();
}
}, [isScrollAtBottom]);
useIsScrollAtEnd のフックを実装することで、無限スクロールを簡単に実現できるようになりました。
関数コンポーネント + hook はクラスコンポーネントの代わりに使用できます。
クラスよりもシンプルで、コードがとても読みやすくなります。
また、hook は関数コンポーネント内のどこでも再利用できるので、そういった観点からもとても便利です。
是非、皆さまも活用してみてください。
また、弊社では開発からサービスの運用まで、幅広くご支援させていただいております。
是非一度
ください。
また、詳しいサービス内容に関しては、当社ホームページの
(新しいタブで開きます)をご参照ください。
https://spice-factory.co.jp/contact/

(新しいタブで開きます)
クライアントのデジタルトランスフォーメーションを幅広く支援するスパイスファクトリー株式会社、インフラエンジニアの松浦です。
この記事では、Active Directory のマネージドサービスとして展開されている AWS Directory Service を用いてユーザ管理基盤を構築するケースについて考え、まとめていきます。
社内ネットワークに対する情報セキュリティ管理のためには、利用者ごとに適切な権限設定を行う必要があります。
こういった管理のための仕組みをユーザ管理といい、ユーザ管理を行うシステム全体の事をユーザ管理基盤と呼びます。
例えば、Windows を利用していると、 Active Directory が利用者を管理します。
使う PC が Active Directory に登録され、利用者が PC のユーザとして作成されます。
利用者が PC でログインする際に、ID とパスワード(ドメインも)を求められますが、このタイミングで Active Directory サーバに認証・共有ネットワーク利用の許可をもらうことになります。
そうすることで社内の共有サーバやプリンターの利用が許可される仕組みがユーザ管理です。
ActiveDirectory をユーザ管理基盤として利用すると共有ネットワークだけではなく Office365 などの外部サービスへSSOで利用できるようになります。
ユーザ管理基盤に認証をおこなうことで、 VPN の利用や SSO の認証を一元管理することができ、利便性もあがります。
Active Directory とは、Microsoft がつくった PC などを管理するディレクトリサービスになります。
WindowsNT のころにはすでに存在していたもので、共有ディレクトリや共有プリンタなどを簡単につくることができます。
PC を登録することにより、ユーザ管理や権限をきめ細かく制御することができます。また、GUI で管理ができるため Windows に慣れている人であれば管理しやすいでしょう。
今やLDAPサーバとしても使えるようになってきており、Kerobers 認証をすれば Linux をPC同様に管理することも可能になります。
しかし、SSH-KEY が標準で登録できない、LinuxOS(CentOS6系など)で Kerobers が使えずLDAPサーバが必要になる、など Linux で利用するには注意が必要です。
ここで LDAP という単語が出てきましたが、LDAP とは古くからあるディレクトリサービスで、DC や OU などを持つツリー構造でユーザや機器を管理するものです。
基本 CUI で管理し、LDIF という形式のファイルで登録削除をおこないます。
GUI は JAVA ベースの管理ツールがありますが、個人的にはインターフェースがわかりにくく使いづらい印象です。
また、LDAPサーバの中にもいくつか種類があります。OpenLDAP 以外にも商用バージョンのものがあったり、Active Directory がLDAPサーバとして利用できたりします。
構造も共通ではなくそれぞれ違いが存在し、LDAPクライアントの指定で吸収することもあります。
柔軟な仕組みで、用途によってツリーを作ることができる為、管理がしやすいのが特徴です。
Unix系OSのログインに使う LDAP は、ログインするための外部認証サーバという位置付けになります。
ネットワーク機器にも使えるためデータセンターといったような端末が多い所でよく使われます。
また、SSH-KEY もLDAPサーバに保存されるため、サーバ側はLDAPサーバの指定をすることでログインすることができるようになります。
これらの認証には PAM という仕組みを利用しており、OS に登録してあるユーザと LDAP を利用するユーザが違和感なく利用可能になっています。
PAM はプラグインのように複数の認証を可能にしており、Active Directory との連携も可能になっています。
そもそも、ユーザ管理はどのようなときに行われるのでしょうか。
社内ネットワークに対する情報セキュリティ管理のために使わるため、やはり、企業組織でのPC管理などで使われることが多いです。
具体的には、Active Directory サーバでプリンタの共有やファイル共有を行うなどです。
PCにログインすると、ドメイン認証がおこなわれ、プリンターやファイル共有が利用可能になるイメージです。
こういったユーザ管理の為に、管理者はActive Directoryサーバでユーザの登録や削除を行います。
もう一方の LDAP も同じようにサーバやネットワーク機器のログインが共通化されます。
Active Directory はLDAPサーバとして利用できるため、サーバやネットワーク機器のログインも共通化することができます。
ユーザ管理を共通化することが、利便性の向上や管理負担の削減に有効なことは、先程説明した通りです。
しかし、いまは PC だけではなく Google Apps や MS Office Online などWebを使ったアプリケーションも普及しているため、社内の Active Directory だけでは管理が十分でない事もあります。
そこで、ユーザ管理をインターネット側でも利用可能にするよう、システム基盤を整備していく必要があります。
そのために、ローカルだけの管理から他へ管理する基盤をひろげる、要はシステムやネットワークを組み合わせて管理する対象を広げるために基盤を作っていきます。
そうしてシステムを拡張し、ユーザ管理基盤を作っていきます。
Linux で Active Directory をLDAPサーバとして利用するには SSH-KEY などの拡張が必要です。
以前と比べ使いやすくなってきましたが、クラウドなどのインフラで利用するにはローカルに構築した Active Directory では少々難があります。
そこで、AWS Directory Service という Active Directory のマネージドサービスを利用します。
AzureAD はフェデレーションサービスを利用し同期することで Azure の認証を localAD と連携することができます。
尚、AWSなど他のクラウドでは利用し辛い事も多いのでご注意ください。
Azure ADと比較して AWS Directory Service はフルサービスの Active Directory ということもあり、ADドメインのプライマリとして利用可能のようです。
社内Active Directoryとの同期には VPN などを利用します。AWS Site-to-Site VPN・AWS Direct Connect などで接続を行います。オンプレとの同期は信頼関係をつくることで同期することができます。
通常の Active Directory と同じ運用が可能なところが使いやすそうですね。
AWS SSOと Active Directory を連携させことでシングルサインオン(SSO) が提供されます。
また、外部との連携には SAML を使用できます。
アプリケーションで認証を統合することもできそうで、AWS Cognito と組み合わせることでスマートフォンアプリとの連携も可能になります。
AWSコンソールの利用だとスイッチロールがありますが、よりシームレスな切り替えが可能になりそうです。
このように便利なユーザ管理ですが、情報漏洩等のセキュリティ面を最大限考慮し、対策を取る必要があります。
基本的な考え方として、LDAP/ADを外部公開しないようにするなどが重要です。
そのためには、以下が代表的な対策になります。
さらに、以下も同時に行うことで情報漏洩リスクを下げることができます。
大変重要な事ですので、必ずユーザ管理の取り組みとセットにして考えるようにしてください。
AWS Directory Service でユーザ管理を考えてみました。
業務系のアプリケーションやユーザ管理に向いているのでは、という点に対しては予想通りではありました。
しかし、Cognito の認証として利用することで、スマートフォンからデータを直接送信し Athena で検索させるような仕組みの認証基盤として使えそうだというのは、全くもって新しい発見でした。
また、ユーザ管理を一元的にできるので監査などもスムーズに対応できそうだと感じました。
古くからある技術と最新の技術を組み合わせる事で面白い発見が多くあったので、是非皆さまも色々挑戦してみて下さい。
また、弊社では開発からサービスの運用まで、幅広くご支援させていただいております。詳しいサービス内容に関しては、当社サービスページをご参照ください。
(新しいタブで開きます)
=>
(新しいタブで開きます)

スパイスファクトリー株式会社、エンジニアの都賀田です。
業務では主に Ruby on Rails を利用して、Web 開発を行なっています。
私事ですが、最近開発用エディタを Vim から RubyMine に変更しました。
現在使用を始めて早数週間が経とうとしていますが、個人的に RubyMine は便利だと感じています。
この記事では、Vimmer であった私が RubyMine に変更した際の感想と、RubyMine の機能を紹介していきたいと思います。
そもそもですが、私が Vim を使っていた理由は以下です。
Vim の利用に付随して、日頃からターミナルを利用することになり、Linux コマンド(cd や ls 等)や様々な CLI ツールの利用に対する苦手意識がなくなりました。
また Vim は Web エンジニアの利用が想定される環境では基本的に利用可能で、エディター上の移動にマウス操作を必要としません。
今回 RubyMine に乗り換えた理由は、以下です。
特に、開発メンバーで同じものを使いたいという点については、プロジェクトメンバーで同じものを使った方が教えあったりするときに便利だろうと日々思っていました。
また Vim は設定が自由であり、拡張性がある一方で、必要な機能を探しては設定をする必要があり、徐々にその管理が大変だと感じるようになっていました。
そのため、この機会に RubyMine をちゃんと使ってみようと思いました。
RubyMine を使い始めて慣れるまでには、一週間程度かかりました。
基本的には、ショートカットキーに慣れるまでの時間とイコールだと思います。
ちなみに私は Macbook Pro を利用しているのですが、デフォルトだとファンクションキーがシステム側の機能に割り当てられています。
RubyMine のショートカットキーは、ファンクションキーをふんだんに使っているので、これを変更しました。
ファンクションキーを利用するには、システム環境設定 > キーボード > F1, F2などのキーを標準のファンクションキーとして使用を選択します。
元々のシステム側の機能は、Fnキーと合わせて押下することでそのまま利用できます。

ここからは RubyMine を利用する上で、知っておくと便利な機能をご紹介します。
よくわからないメソッドの定義元に Cmd + B(もしくは Cmd 押しながらクリック) で飛んでくれます。
gem のメソッド等にも飛んでくれるので、そのメソッドの正体をすぐに見つけ出すことが可能です。
Cmd + [ で前に戻る
Cmd + ] で先に進む
定義元ジャンプ機能を繰り返した場合でも、この機能により以前の場所に戻ったり、進んだりすることが可能です。
定義元ジャンプ機能とセットで利用すると便利です。
アクション側に、ビューへ飛んでくれるボタンがあります。
行数の右横にあるアイコンがボタンです。以下の画像の14行目の右横にありますね。

ビュー側に、アクションへ飛んでくれるボタンがあります。
こちらも同じく行数の右横にあるアイコンがボタンです。次の画像の1行目の右横にありますね。
Rails 開発者は、コントローラとビューを行き来して開発を進めていくことがよくあるかと思いますが、この機能は非常に有用です。

Shift + Cmd + Fで文字列による全ファイル検索が可能です。
RubyMine の全プロジェクトファイル内文字列検索は、文字列を入力する毎に、部分一致検索が行われて、マッチした候補が上がってくるというインタラクティブな操作性を持ちます。
文字列入力毎に、候補が一覧で提示されるため、検索対象の文字列が多少曖昧でも自分の求めている記述部分に辿り着きやすいと言う利点があります。

例えば利用用途として、ブラウザの devtools 機能で調べた要素などが、実際にはどこのファイルに記述されているのかを id や class の値等で調べるときなどに有用です。
Shift 2回押し でポップアップ表示され、こちらも部分一致検索で絞り込み可能です。

おまけです。
私が Vim を使っていたこともあり、Vimmer の人がいきなり RubyMine の様な IDE を利用すると、Vim 特有のキーボード操作ができないことにストレスを抱えると思います。
このプラグインを入れることで、基本的な Vim のキーボード操作がすぐに機能するようになります。
Preferences > Plugins の中で検索してインストールしましょう。
Preferences は Cmd + ,で開けます。

RubyMine は機能が豊富で最初は何を使ったらいいか迷うと思います。
ただ、使いこなすことができれば、開発効率を劇的に向上してくれる力強い味方になってくれるはずです。
コントローラ内のアクションを列挙してくれる File Structure 機能や DB 接続等、便利な機能はここで紹介したもの以外にもたくさんあります。
ぜひいろんな機能を探して、使ってみて、楽しい開発ライフを送っていきましょう。
また、弊社では開発からサービスの運用まで、幅広くご支援させていただいております。詳しいサービス内容に関しては、当社ホームページの
(新しいタブで開きます)をご参照ください。
ちなみに Vim は今でも好きです。ちょっとした編集や git 操作などであれば Vim でやってしまいます。
立ち上げるスピードもとても早くストレスが一切ありません。今後も使っていくと思います。
一方で、前述したように Vim 操作もプラグインで踏襲しながら利用することができるので、日常の開発業務では RubyMine を利用しています。
そして様々な機能をフル活用することで(まだ使えていない機能も多々ありますが……)、生産性が大きく上がると実感しています。
ぜひこの機会に RubyMine を使ってみてはいかがでしょうか。

スパイスファクトリー株式会社、エンジニアのリンです。
スパイスファクトリーの詳しいサービスは
(新しいタブで開きます)をご覧ください。
近年、React + GraphQL + Apollo Client を組み合わせた開発の人気の高まりと共に、React + GraphQL + Apollo Client の導入について紹介する記事が増えてきています。

2020 state of js data layer 部門GraphQLだけでなく、GraphQL関連のpackage (Apollo Client)も注目されてます
その中で、GraphQL のつなぎ込みや Apollo が提供する hook などの記事は多くありますが、ローカルステートの管理についての紹介はまだ多くありません。
そのため、Apollo Client を使ったときのローカルステートの管理をどのように設計すべきか参考例と共にまとめていきます。
尚、こちらの記事は、React、redux、GraphQL の知識をお持ちの方を対象に説明を進めます。
まず、Apollo Client がアプリケーション内でどのような役割を担うか考えてみます。
その違いによって、ローカルステートの管理の仕方、または運用するパッケージも異なってくるためです。
基本的には、Apollo Client がアプリケーション内で担う役割については、以下の2つになります。
Apollo Client を単なる GraphQL のAPIサーバーへのつなぎ込み、そして取得したデータをキャッシュ化してくれるツールと考える場合は、Apollo Client以外での状態管理が必要になります。
Apollo Client をアプリ全体のデータのコアと考える場合は、Apollo Client の API でローカルステートも管理していきます。
以下、Apollo Client 以外で状態管理する場合と、Apollo Client の API でローカルステートも管理する場合の、それぞれの方針について詳しく見てきます。
Apollo Client以外で状態管理をするなら、GraphQL や Apollo Client を利用しないアプリケーションと大きな違いは無いと考えます。
そのため一般的によく使われる下記のような状態管理のライブラリが利用できます。
Apollo Client 以外で状態管理する場合は以下の留意点があります。
まず、GraphQL に関連するデータが ApolloClient 側に、ローカルステートは他のライブラリにそれぞれ保持されるため、管理し辛い状況が出てきます。
また、データが二重管理になる可能性や、パッケージ数が増えるといった点も考慮する必要があるでしょう。
これらの問題を解決するには、予めルールを作りデータが重複しないよう工夫することがまず考えられます。
その他、Apollo Client の代替として URQL を利用するのもひとつの方法でしょう。
https://formidable.com/open-source/urql/(新しいタブで開きます)
Apollo Client の API で状態管理する場合について考えていきます。
尚、Apollo Client はローカルステートに関して4種類の API を提供しています。
Apollo Client の cache にデータを直接書き込んで、GraphQL の形で呼び出します。
以下のような記述で実現可能になります。
graphQL の変数名の後ろに `@client`を追加すると、Apollo Client はローカルステートとして認識してくれます。
const IS_LOGGED_IN = gql`
query IsUserLoggedIn {
isLoggedIn @client
}
`;
cache.writeQuery({
query: IS_LOGGED_IN,
data: {
isLoggedIn: // ログインの判断処理 e.g. !!localStorage.getItem('token'),
},
});
reactive variable (Apollo 3 系以降)は、どこでも使えるグローバル変数です。
以下ソースコード例です。
import { makeVar } from '@apollo/client';
const isLoggedInVar = makeVar(false);
console.log(isLoggedInVar());
// output: false
isLoggedInVar(true)
console.log(isLoggedInVar());
// output: true
type policies (Apollo 3 系以降)は、GraphQL (Query) を通じて、ローカルステートを呼び出し、type policies が対応するデータを返します。
ローカルステートの中に `isLoggedIn` が使われる時にどういう値を返すかのを定義します。後ほど GraphQL で isLoggedIn も呼び出すことができます。
export const cache = new InMemoryCache({
typePolicies: {
Query: {
fields: {
isLoggedIn: {
read() {
return true;
}
}
}
}
}
});
const IS_LOGGED_IN = gql`
query IsUserLoggedIn {
isLoggedIn @client
}
`;
3系以前で主流だった方法のひとつです。
3系以降でも使えるのですが、廃止予定となっておりかつ API の更新が既に停止しているため、ご注意ください。
尚、API の更新が早かったり、コンセプト自体が他の既存のライブラリーとやや異なるため、学習コストが高いことが懸念点です。
React + GraphQL + Apollo Client でのローカルステートの管理の方法をまとめてみました。
プロジェクトの状況によって、適するローカルステートの管理方法は異なってくると思います。
この記事では Apollo Client が担う役割に基づいて2つの実装方針をまとめましたが、他にも色々な観点があります。
例えば、既に redux を導入しているプロジェクトだと、無理に Apollo Client APIに変更することはあまりメリットがないかもしれません。
また、Apollo Client の API がまだ定まっていないという観点から、Apollo Client の API を導入しないと考えるのもまた合理的だと思います。
私自身は、パッケージを減らすことができ、構造上 SSOT(single source of truth) のコンセプトに近いという視点から、Apollo Client の API を利用しています。
ケースバイケースで適するローカルステートの管理方法が何かを考え、取り組んでいくことが必要でしょう。
また、弊社では開発からサービスの運用まで、幅広くご支援させていただいております。
是非一度
ください。
また、詳しいサービス内容に関しては、当社ホームページの
(新しいタブで開きます)をご参照ください。
https://spice-factory.co.jp/contact/

スパイスファクトリー株式会社Webエンジニアの平山です。
現在は、株式会社サマデイ様が展開されている The Admissions Office(新しいタブで開きます) の実装から、カスタマーサクセスまでを共同開発のかたちで幅広く担当しています。
カスタマーサクセス兼任のWebエンジニアとして入社した私が、サービスのカスタマーサクセス業務に携わり感じた事や、エンジニアがカスタマーサクセス業務を行う意義についてまとめています。
まず、カスタマーサクセスとは具体的に何を目指すものでしょうか。
フリー百科事典『ウィキペディア(Wikipedia)』によると、以下のように書かれています。
カスタマーサクセス (英: Customer success)は、顧客が製品・サービスを使うことで成功し、望ましい結果を達成することを支援するビジネス方法
また、カスタマーサクセスは、「自社の成功のために、顧客に良いものを提供する」という考え方ではなく、「第一に顧客の成功や満足を達成することで、結果的に自社の成功につながる」 という考え方が前提にあります。つまり、カスタマーサクセスにおいて、顧客を成功に導くまでの過程に企業が徹底的に寄り添うことが重要だといえます。
カスタマーサクセスという考え方が普及してきたのは比較的近年のことで、注目を集めるきっかけとなったのがサービスのサブスクリプションモデルへのシフトでした。
カスタマーサクセスは、2018年頃既に米国で一大潮流となっていました。一方で日本では2018年、まだその波は到達した頃で、日本ではこの年が「カスタマーサクセス元年」と呼ばれています。
どちらも CS と略すことができる上、響きも似ているため混同されやすいですが、 カスタマーサクセスはカスタマーサポートは異なる概念です。
比較すると下記のような違いがあります。
| カスタマーサクセス | カスタマーサポート |
|---|---|
| 先んじて回避する、対応する | 壊れたら直す、問われたら答える |
| 能動的 | 受動的 |
| 「リテンション率(継続率)」で成果を判断 | 「1人が1日に完了できる対応件数」で成果を判断 |
ニック・メータ、ダン・スタイマン、リンカーン・マーフィー『カスタマーサクセス サブスクリプション時代に求められる「顧客の成功」10の原則』(英治出版、2018年)より
どちらかだけが必要ということではなく、異なる役割を持つものであるという認識が重要です。
組織の大小や、体制によってエンジニアとカスタマーサクセスの関わり方は様々です。
弊社では、サービスの共同開発者として良いものをよりスピーディに作っていくため、エンジニアである私がカスタマーサクセスの業務も兼任しています。
エンジニアがカスタマーサクセス業務を担う意義としては、下記のようなことが挙げられます。
エンジニアがカスタマーサクセス業務に入る事で、エンドユーザーの意見を直接聞くことができます。サービスそのものを実装・構築する提供側でありながら、 実際の利用者の声をきくことが「ユーザーにとってより良いシステムにする」という意識に繋がります。
またサービスは、つくって終わりではなく日々改修を重ねていかなくてはなりません。
エンジニアがカスタマーサクセス業務に入る事で、昨日のユーザーからの声を今日実装に活かす、といった事も可能になり、サービスの品質向上の精度とスピードが上がります。
カスタマーサクセス担当は、画面上の動線変更やWeb上でのヘルプページの追加など、施策を行いたいときにそもそもシステムとして可能か、またどういった要件が必要かを検討しなければなりません。
エンジニアというシステム要件を把握している人材がこのポジションにつくことで、現在のシステムを上手く利用した実現可能性と費用対効果の高い打ち手を提案することが可能になります。
カスタマーサクセス業務においてのコミュニケーションがシンプルになります。
また、カスタマーサクセス → エンジニアという伝達の工程をカットできるため、エンジニアチームへの共有も行いやすいです。自らも開発に加わることができるので、施策実行や課題解決への動き出しも早くなります。
Webエンジニアの私自身が、実際にカスタマーサクセス業務を行ってみて感じたことを紹介していきます。
自分の実装したシステムについて、直接ユーザーから感想を受けることができるので、やはりやりがいに繋がります。
もちろん、マイナスな意見を頂いた際は落ち込むこともありますが、開発者・施策提案者として勉強になると感じます。
ユーザーの意見は本当に貴重です。私自身も「この不満に対し、何を解決すればいいのだろう」というところから、新しいアイデアが生まれることがあります。
そこから実際に施策まで落とし込むのは大変ですが、エンジニアの視点だけでは思いもつかないような意見からアイディアを出せるのは、この業務の面白い部分であると思います。
カスタマーサクセスに携わる以上、常に念頭に「よりユーザーにとって良いものは?」という考えを持っておく必要があります。
「機能」を実現する上で、その先にいるエンドユーザーを想像しながらの開発はエンジニアのキャリアとして貴重な経験になっていると日々実感します。
「カスタマーサクセス」という響きから、画期的な何かを行なっているようにも思えますが、実際には地道な作業も多かったりします。
それがユーザーの為に繋がることであるなら、機能開発以外にも行うべきことは多いです。
マニュアルの見直しや、テキストの変更などもその一部であり、まだまだやれることは山積みです。
Webエンジニアとしてカスタマーサクセス業務に携わる意義や感じた事についてまとめました。
弊社は受託開発会社ですが、開発をするサービスと真剣に向き合い、カスタマーサクセスの領域まで幅広く支援を行っています。
納品して終わりではなく、納品後も引き続き責任を持って関わっていくという姿勢は弊社ならではです。興味がおありでしたら是非
ください。
カスタマーサクセスの体制や業務内容については、スパイスファクトリーとしてもまた担当者である私自身もまだまだ試行錯誤中ではありますが、ユーザにとってより良いものを提供できるよう引き続き取り組んでいきます。

参考
– 英治出版『カスタマーサクセス サブスクリプション時代に求められる「顧客の成功」10の原則(新しいタブで開きます)』
著書:ニック・メータ、ダン・スタイマン、リンカーン・マーフィー
最新テクノロジー、UIUX、アート、マーケティングなどあらゆる技術・メソッドを用いてクライアント企業のデジタルトランスフォーメーションを支援しているスパイスファクトリー株式会社です。
詳しいサービスに関しては
(新しいタブで開きます)をご覧ください。
こちらの記事では、活用事例、メリット・デメリット、導入方法についてをお伝えしていきます。
執筆協力:ダイナミックプライシング 研究組織「マテマ」http://mathema-tech.com/(新しいタブで開きます)

ダイナミックプライシングとは、よく売れる商品の価格を上げ、あまり売れない商品の価格を下げることで、売上を最大化することを指します。
価格はAIによって自動的に調整されるため、人が価格を決めるよりも正確で、労力もかかりません。
売上を最大化するだけでなく、在庫量や生産のリードタイムに合わせて、販売スピードを調節し、目標期日に完売するといったことも可能です。
今、ダイナミックプライシングが注目される理由は何でしょうか。
導入事例から考えていきましょう。
ダイナミックプライシングの成功事例としては、ホテル予約サービスのOYOや民泊サービスのAirbnbが有名です。
特にOYOのプライシングは洗練されており、RevPAR(revenue per available room:一室あたりの売上)を最大化するため、一時間あたり14万件という大規模なデータを元に、全世界の宿泊料金を一日に6000万件変更することが可能になっています。
これにより、適正価格を提示してユーザの心を掴むことにつながり、創業から6年で客室数世界第2位の企業へと成長しました。
また、最も身近にダイナミックプライシングを体験できる事例はAmazonでしょう。
多くの人が商品購入のページに価格変動のグラフが表示されているのを目にしたことがあると思います。Amazonはダイナミックプライシングを導入後、2013年には1日に250万回以上価格調整を行うことで、売り上げを前年比27.2%伸ばすことに成功しています。
このように、ダイナミックプライシングは適切に導入されれば、企業の成長を強力に促すパワーを持っています。
さらに、ECの普及によって商品の販売情報が蓄積され、ダイナミックプライシングに必要なデータが手に入りやすくなったことも導入を推し進める理由の一つとなっています。
特に、AmazonやアリババといったECプラットフォーム上では日々膨大なデータが収集されており、精度の高いプライシングを可能にしています。
ではダイナミックプライシングはどのようなビジネスにも適用できる万能のツールなのでしょうか。
実は業種や取り扱う商品によって向き・不向きがあります。
ダイナミックプライシングが最もうまく働くのは、「賞味期限のある商品」です。
例えば人気のライブやスポーツ観戦のチケットは、イベント日に近づくほど入手が困難になり、値段が高騰します。
しかし、イベント日を過ぎると価値が無くなってしまい、転売しようとしても買いたいと思う人は誰もいないでしょう。
飛行機のチケットも同様に、フライト時刻を過ぎると価値が無くなってしまいます。
また、ホテルの部屋は予約の際に宿泊日を指定する必要があります。
このため同じ部屋でも宿泊日ごとに別のお客様に販売できる別の商品であると考えられます。
そしてやはり宿泊日を超えると予約の価値は無くなってしまいます。

また、毎年の流行に影響を受けるアパレル業界も同様です。
流行に敏感な顧客は代わり映えのしない品揃えには興味を持たないため、常に新しい商品に入れ替える必要があります。
そのため、商品には販売可能なシーズンがあり、シーズンを過ぎると価値が激減してしまいます。
このように、「ある期限を超えると価値がゼロになる商品」は、共通して「価値が時間とともに変化する」という性質があるため、価格を動的に変更するダイナミックプライシングに向いています。
このような期限付き商品を扱う業種としては、以下が例として挙げられます。
魚や野菜などの生鮮食品もまさに賞味期限のある商品なので、ダイナミックプライシング向きではありますが、期限が時間単位と短いため、技術的にはより難易度が高いでしょう。
また、「商品のオリジナリティ/希少性」も重要です。
例えばどこでも売っているようなボールペンをAmazonで販売する際、他の店が100円で販売しているのに、自分の店だけ200円で販売しても買ってもらうのは難しいでしょう。このような、どこにでも売っている商品(コモディティといいます)は市場価格が明確で、ダイナミックプライシングを適用する余地がありません。
ですがもし、ボールペンに流行りのアニメ柄がついており、他の店で取り扱いが無い場合は、150円に価格を設定しても売れるかもしれません。極端な例ですと、世界に一つしかない名画には市場価格が存在しないため、プライシング技術は必要不可欠です。
このような希少性のある商品を扱う業種としては、以下の例が挙げられます。
では次に、ダイナミックプライシングに不向き、失敗に繋がりやすいケースを見てみましょう。
これは先程のうまく行くケースの裏返しです。
価値が安定していて、時間が経っても変わらないような商品はあまりダイナミックプライシング向きではありません。
例えば昔から変わらない値段で売られているカップラーメンの価格がある日突然倍になったら、顧客から反感を買うでしょう。
最悪、ブランドイメージを損ね、企業の業績悪化にもつながりかねません。価格を変更するには、「価値が一定ではない」と顧客が納得するための根拠が必要です。
飛行機のチケットやホテルであれば、ある程度の価格変化は受け入れてもらえるでしょう。
また、Amazonではすでに当たり前になっているダイナミックプライシングですが、場合によってはデメリットもあります。
多くの人はAmazonで欲しい物を買う時、できるだけ安い物を探すはずです。
売る側もそれを知っているので、競合店の価格を調査し、できるだけそれより安い価格にしようと努力します。
しかしもし、全ての店舗が競って最安値をつけようとすれば、結果として価格は0円に収束してしまい、商売が成り立ちません。
ダイナミックプライシングは単純に競合価格を基準にするのではなく、「いくらにしたらどれくらいの人が買ってくれるか」という顧客の需要データを基準にして価格を決めなくてはなりません。
しかし、Amazonのような競合がひしめき合ってダイナミックプライシングを使っているプラットフォームでは、価格競争に巻き込まれて失敗する可能性があるでしょう。Amazonに価格競争で勝つ、という考えはあまり現実的ではありません。
価格競争を避けるには、商品にオリジナリティが必要です。
また、今説明したように、ダイナミックプライシングで最適価格を計算するためには顧客の需要データが必要です。
しかし、ECサイトを立ち上げたばかりの新しい店舗の場合、販売データが蓄積されておらず、ダイナミックプライシングをすぐには開始できません。
更にいうと、販売数は価格によって変わります。同じ商品なら価格が高いときよりも安いときほうが多くの人が買うからです。
つまり、ダイナミックプライシングを行うためには、いろいろ価格を変化させたときの販売数データを収集する必要があります。
データの収集には時間がかかるため、データが少ない導入初期にはダイナミックプライシングがうまく機能しない可能性があります。
このように、ダイナミックプライシングにも弱点はあり、必ずしもうまく行くとは限りません。
しかし後ほど説明するように、新しい技術によってこれらの問題を解決することも可能です。
これまで述べたように、ダイナミックプライシングを導入することで、ビジネスを大幅に改善/成長できる可能性があります。
幸い、いくつかのECプラットフォームは既にダイナミックプライシング機能を提供しているので、自分でシステムを一から開発する必要はありません。
ただし、プラットフォームごとに設定できる項目や機能が異なるので、ご自身のビジネス/商品に合ったプラットフォーム選ぶ必要があります。
例えばAmazonに商品を出品することで、Amazonの提供する自動価格設定機能を簡単に利用することができます。しかし先程述べたように、他の競合店や、Amazon自身との価格競争に巻き込まれてしまうので、商品にオリジナリティが必要です。
ダイナミックプライシングの導入は、適切な手段を選択することで導入ハードルがぐっと下がり、また導入後素晴らしい恩恵をもたらしてくれることも多い技術です。
弊社提供サービスは、ビジネスに合わせたカスタマイズも相談可能です。是非一度
ください。
また、詳しいサービス内容に関しては、当社ホームページをご参照ください。
=>
(新しいタブで開きます)
ダイナミックプライシング 研究組織 マテマ
“数学で世界をより良く”をコンセプトに掲げている研究組織。数学的に動作保証された最先端AIで、企業・団体のビジネスをサポート。
http://mathema-tech.com/(新しいタブで開きます)
(新しいタブで開きます)システムやサービスの受託開発の会社を探すとき、実績や予算、納期など気になる部分は色々あるかと思います。
今回はそこから一歩踏み込み、「どのような開発手法でシステムの開発を行う会社か」という視点から開発会社を見るために、システムの開発手法と、その一つであるアジャイル開発についてご紹介したいと思います。
また弊社の詳しいサービス内容は
(新しいタブで開きます)をご覧ください。
システム開発手法について理解するためには、まずどのようなシステム開発が良いシステム開発か? ということを考えなくてはいけません。
「良いシステム開発」というのは抽象的な表現になってしまいますが、ここでは以下の二つの条件を満たすものを「良いシステム開発」として仮に定義していきたいと思います。
当たり前の事のように思えるかもしれません。
しかし、この二つを満たすことができないケースは少なくありません。
「実際に開発を始めてみたら想定以上に必須機能が多く、さらに複雑で高度な機能も多いため、予算や納期の中での完成が困難という事が開発の途中で判明」
「システムを利用する業務のフローが開発当初とは変わってしまい、システムが完成したは良いが大幅な修正を行わないと使い物にならない」
このような事態を回避するために重要となるのが、どのように開発を進めていくか、つまり開発手法です。
そして、どのような開発手法を選択するかは「良いシステム開発」だけでなく、より使いやすいシステムやサービスを作るためにも重要になります。
システム開発を大きく左右する開発手法ですが、現在システムの開発手法は大きく分けて二種類あります。
一つ目のウォーターフォールモデルは古くから使われている開発手法です。ウォーターフォールモデルは下記のように開発の各フェーズを順番にこなしていく、シンプルな手法です。
対して、アジャイル開発はシステムを機能ごとに小さく分割し、その小さな機能単位に開発、リリースを繰り返していく手法です。

海外ではアジャイル開発が主流となりつつありますが、まだ日本ではアジャイル開発を採用している会社は少ないのが現状です。
しかし、プロジェクトによって適切な開発手法を選択することは、良いシステム開発のために重要です。
今回は、その中でも徐々に広まりつつあるアジャイル開発について、その特徴やメリット、使いどころを解説していきたいと思います。
アジャイル開発とは開発の指針を示す方法論の事を意味しており、アジャイル開発に含まれる開発手法には様々なものがあります。
その中で共通して言えるのは、アジャイル(agile : 機敏な、素早い)という言葉がさすように、小さい開発スパンの繰り返しによって螺旋階段のようにシステムの開発を行っていく、という部分です。
具体的に言うと、アジャイル開発は開発するシステムを機能単位に小分けにし、その小さな単位ごとに要件定義、設計、実装、テスト、という工程を繰り返していきます。
このときのスパンはプロジェクトにもよりますが、大体1週間から1カ月くらいの長さになることが多いと言われています。
また、アジャイル開発の特徴の一つとして、最初の開発スパンが完了した時点で実際にある程度動くものに触ってみることができる、という点が挙げられます。
(新しいタブで開きます)
アジャイル開発の定義はアジャイルソフトウェア開発宣言(新しいタブで開きます)に記載されており、そこではアジャイル開発の原則(新しいタブで開きます)についても触れられています。
ここで宣言されているアジャイル開発の原則・前提とは、計画や契約よりも顧客の満足を優先し、その実現のために変化に対応し価値のあるシステム開発を行う、と言うものです。
そのためにはまず、最低限動くシステムをなるべく早く開発すること。そして、それをベースとしてエンジニア同士はもちろん、クライアントとも密にコミュニケーションを取り合いながら開発を進めて行くこと。その上で、変化する状況に柔軟に対応し、より良いシステムを開発するために継続的に取り組み続けることを目標とします。
これが、アジャイル開発の根底にあるスタンスです。
アジャイル開発では、小さな機能単位に分割して少しずつ開発してきます。
そのため、システムを利用する業務の変更や状況の変化があった場合にも、それに合わせてシステムの軌道修正を行いやすい、と言うメリットがあります。
ウォーターフォールモデルで開発を行った場合、要件変更の影響があまりに大きく、対応に膨大な時間がかかってしまうような状況が発生するリスクが高くなります。
完成したシステムに触ってみたらイメージしていたものと違っていた、と言うケースは少なくありません。
どのようなシステムが欲しいのかを、いきなり100パーセント開発会社に伝えるのはかなり難しい事だと思います。
まず最低限動くものを作ってもらい、それをベースにどのようなシステムにするかを話し合いながら徐々に開発をしていく、という方が開発を依頼する側にとっては少ない負担で理想のシステムを作る事につながります。
どのようなシステムが欲しいか完成形が具体的にイメージできていなかったとしても、欲しいシステムを目指して一歩一歩開発を進めていく事が出来ます。
これは上記の二つのメリットを合わせたメリットです。
少しずつ出来上がっていくシステムを実際に触り、そこから次に作る機能の決定や既存の機能の修正を行い、さらに段階的なリリースをすることで、システム開発を進めながらPDCAサイクルを回すことができます。
少しずつ機能を開発し、変更にも柔軟に対応していくという事は、裏を返せば先の見通しが立ちづらいという事になります。
もちろん、アジャイル開発の場合も納期や予算のラインをある程度決めて開発を行なっていきますが、そこに収めるためには柔軟に機能の取捨選択などを行うことが求められます。
短いスパンでの開発を繰り返すため、システム開発を行うプロジェクトのコントロールが難しくなります。
さらに、開発に携わるエンジニアに求められるレベルも格段に上がります。
技術についてはもちろん、しっかりコミュニケーションをとり、仕様やクライアントの事を深く理解し、何を求められているか自分で考えることができる能力がエンジニアひとりひとりに求められます。
クライアントは、予算と納期と要件を開発会社に丸投げしてあとはすべて任せる、という事が出来なくなります。
エンジニアと密にコミュニケーションを取り合いながら、次にどの機能を追加もしくは修正するかを決定し、要件に変更がある場合はそれについて議論を行う。
このように、一歩ずつシステムの完成に向けてエンジニアとのやり取りを頻繁に重ねていく必要があります。
アジャイル開発が向いているケースとして、例えば、システムやサービスを必要としているが、具体的にどのようなものが必要なのかが明確ではない場合などが挙げられます。
このような場合、とりあえず最低限動くものに触りながら必要な機能を順番に決定していき、試行錯誤を行いながらシステムやサービスを完成に近づけていくことができます。
より具体的な例として以下のようなケースが挙げられます。
これらのケースではアジャイル開発の持つ速度、柔軟性が大きく影響してくるでしょう。
特に新しいサービスの開発については、最低限の機能のみを開発したリスクの少ない状態でリリースを行い市場の反応を見ることができるため、とてもアジャイル開発と相性のいいケースと言えます。
逆に、アジャイル開発があまり向いていないケースとしては、既存のシステムのリプレイスを行う場合、欲しいシステムの要件が細部まで明確に決まっている場合などが挙げられます。
関連記事:新規事業担当者必見。“アジャイル開発”で小さく始めるシステム開発(新しいタブで開きます)
どのように開発を行っていくか、というガイドラインである開発手法は、プロジェクトの成功やどのようなシステムが出来上がるか、という部分に大きく影響します。
システムが必要な背景やどのようなシステムを目指したいかによって、どの開発手法を採用するかを慎重に決定しなければいけません。
必要なシステムやサービスのイメージが細部まで明確に出来ている場合には、ウォーターフォールモデルによる開発が適切であるかもしれません。
しかし、どのようなシステムやサービスが欲しいのかがはっきりと定まっておらず、環境に合わせながら柔軟に開発を行なっていきたい場合には、アジャイル開発が最適な開発手法です。
アジャイル開発は、システムやサービスを育てる開発手法と言えます。
(新しいタブで開きます)今回は、あまり見かけないようで意外と必要になる「複数のテーブルに対して多対一で紐づくテーブル」の設計について、4つのアプローチをご紹介します。
ポリモーフィック関連、複数の関連テーブル、親テーブルの作成方法や分割。また、どの方法を用いて設計を行うかの判断基準も解説します。
弊社スパイスファクトリーでは設計において豊富な実績があります。弊社の概要やサービスプラン、過去の導入実績などをまとめた資料をご用意しました。
気になる方はこちらからダウンロードしてください。
あるテーブルが複数のテーブルのいずれかに対して、自身が多、紐付き先が一で関連する場合のテーブル設計です。
例えば、「記事」と「画像」を投稿できるようなSNSを想定します。
この時、閲覧者が投稿された「記事」と「画像」のどちらにも「コメント」をつけることができる機能があったとします。
このような場合に、どのようなテーブルの設計方法があるのか、以下から説明していきます。
SQLアンチパターン(新しいタブで開きます)にも登場するこの設計方法。「どのテーブルのどのレコード(id)に紐づくのか」という情報をテーブルに持たせてしまうという方法です。具体的には以下のような設計になります。
comments.target_tableに関連する対象のテーブル名を、comments.target_idに関連する対象レコードのIDを格納します。
例えば、以下のようなレコードが入ります。
シンプルな設計方法ですが、SQLアンチパターンでも取り上げられている通り、あまり良い設計ではないと言えます。
具体的には、外部キーの設定ができないため、commentsが紐づく対象について保証することができないというデメリットがあります。
そのため、整合性の保持が完全にアプリケーション側に依存する事になってしまいます。
また、target_idが示す先のテーブルがレコードによって変化してしまうというのは、気持ち悪く感じてしまう人もいるのではないでしょうか?
しかしながら、Ruby On RailsのActiveRecordなどの一部のORマッパーはこのポリモーフィック関連をサポートしているため、そのようなORマッパーを使用する際にはこの方法を使用することをお勧めします。
紐づく対象のテーブルごとに関連テーブルを作成する方法です。以下のような設計になります。
個人的にはあまり無理のない分かりやすい設計ではないかと思います。
1つのコメントが記事と画像の両方に対して紐付かないよう制約をかける事ができない、というデメリットはあります。しかし、対応しているORマッパーを使用しなかった場合の「1.ポリモーフィック関連」の方法と比較すると、データの整合性の担保という観点ではこちらの方法のほうが良い設計になります。
この設計の場合は以下のようなレコードが入ります。
親テーブル(基底クラス)が抜けているために設計がうまくできない、というケースも要件によってはあり得ます。そのような場合は、以下のような設計が考えられます。

記事(articles)と画像(photos)の親として投稿(posts)テーブルを作成します。
この設計方法でも、1つのコメントが記事と画像の両方に紐づかないように制約をかけることができません。厳密にいうと、1つのコメントは1つの投稿に対してのみ紐づきますが、1つの投稿に対して記事と画像の両方を紐付けることが出来てしまいます。
しかし、今回の例に挙げたような「記事や画像の投稿に対してコメントをつける」というケースであれば、背景となるサービスの仕様やプロジェクトの状況などにもよりますが、綺麗な設計と言えるのではないでしょうか?
紐づく対象のテーブルが頻繁に増加するような場合には特に考慮したい設計です。
そもそも、本当にcommentsを一つのテーブルに保存する必要性があるのか?というアプローチです。
要件として、commentsを一つのテーブルにまとめておいたほうが今後都合がよい、という場合もあります。
しかし、もしもそのような状況ではないのなら、最初からテーブル自体を分割しておくという選択肢も十分にあり得るのではないでしょうか?
現状で紐づく対象のテーブルが少なく、今後も増える可能性が低い場合には考慮したい設計です。
サービスの仕様やプロジェクトの今後の見通しなど様々な要因が絡んでくるため、一概に「この方法が最強!」とは言えません。
結局のところはすべてケースバイケースとなってしまいますが、どの方法を用いて設計を行うかの判断基準を簡単にまとめます。
いかがでしたでしょうか?
ちなみに私は「3.親テーブルの作成」や「2.複数の関連テーブル」のアプローチが好みですが、アプリケーション側の実装をする際にjoinするテーブルが増えることを考えると、少し気が滅入ってしまいます。
弊社スパイスファクトリーは豊富な実績を持ち、これらのプロセスを効率的に進めるためのサポートを提供いたしております。
詳細を知りたい方は、こちらからサービス紹介資料をダウンロードしてください。
こんにちは、Webエンジニアの泰です。
今回は爆速フレームワークとして名高い、Phalconをご紹介していきます。
PHPはフレームワークが多く、設計の段階でフレームワークの選定が非常に重要となってきます。API開発の事例を交えて、Phalconを選んだ理由をお話します。
Phalconは2013年に発表され、PHP最速フレームワークとして話題になりました。そのスピードは今なお健在で、PHP Framework Benchmark(新しいタブで開きます)でも圧倒的な結果を残しています。その速度の秘訣はZephyr(新しいタブで開きます)を使用した、PHP拡張機能としての実装です。
CakePHPなどのフレームワークでは”コア”がPHPファイルで存在し、様々な機能を提供する為にゴリゴリと実装されています。シングルトンパターンや遅延ロードなど様々な方法を利用して省メモリの工夫をしていますが、比較的大規模なPHPコードが走っています。Phalconの場合はPHPよりも低いレイヤで処理が書かれているため、高速でかつ省メモリを実現できています。
今回僕が行った案件では次のようなAPIの開発を行いました。
RESTでの設計を行ったため処理内容は非常にシンプルでした。しかしリクエストが頻繁に行われるため、フレームワークとしてもある程度のパフォーマンスが必要な状況です。規模としてはそれほど大規模なものではないので、プログラムとしてもシンプルな構成にしたいという考えていました。そこでPhalconを実戦投入してみました。
Phalconのメリットとして実感できたのは以下の3点です。
Phalconは非常に自由度が高いため、開発時にきちんと設計を行っていれば様々な環境に対応できます。構成によってはCakePHPのようにMVCでフォルダ分けを行い、それぞれのClassを使用した実装を行うことができます。ですが今回のような規模のAPIを実装する場合はマイクロ構成を使用する事で、不要なAPIの読み込みをなくすことが可能です!全体のコード量が少なくなり、動作の軽量化にも繋がるので、他のフレームワークにはなかなかないメリットかと思います。
マイクロ構成でのアクションの実装は以下のようになります。
// app.php
use Phalcon\Mvc\Micro;
$app = new Micro();
/**
* アクション開始時の処理
*/
$app->before(function() use ($app) {
});
/**
* アクション終了時処理
*/
$app->finish(function() use ($app) {
});
/**
* 例外時処理
*/
$app->error(function($exception) use ($app) {
});
/**
* NotFound時の処理
*/
$app->notFound(function() use ($app) {
});
/**
* POSTの場合
*/
$app->post('/users', function() use ($app) {
});
/**
* GETでURLにIDを含める
*/
$app->get('/users/{user_id:[0-9]+}/articles', function($userId) use ($app) {
});
$app->handle();
ソースコードの見通しが非常に良いですね!上記サンプルは最小単位に近い状態なので、ここから設定ファイルやDIでの実装などを追加していく形になります。
REST APIの実装を行う場合はURLとHTTPメソッドがポイントとなるため、ひと目でエンドポイントを把握できるこの構成はメンテナンス性の向上に繋がります。エンドポイントが多くなってきた場合でも、クロージャをControllerクラスに置き換えたり、ファイルに分割してrequireするなどの対応が可能になっています。
他のフレームワークにはなかなかない強みをもつPhalconですが、注意しなければならない点もあります。
個人的に感じた点としては
といった部分です。Phalconは規約の縛りが非常に弱いため、こちらで規約を整備しなければなりません。Phalconでの設計ノウハウが非常に重要となってきます。
また、メール送信処理など一部の機能はincubator(新しいタブで開きます)と呼ばれるPhalconのライブラリ集を使う必要が出てきます。
Phalconは他のフレームワークと比べて素のPHPに近い自由度でコードを書くことができます。今回ご紹介したマイクロ構成以外でもシングルモジュールやマルチモジュールなど構成を変えることでMVCのプロジェクトを作成することが可能です。注意点がクリアできる場面であれば、僕はPhalconでのAPI開発をおすすめします!
(新しいタブで開きます)