tmuxのプレフィックスキーを変更する

tmuxは プレフィックスキー + 任意のキー の組み合わせでショートカットキーが作られており、そのショートカットを使って操作をする。

デフォルトだと Ctrl + b がプレフィックスキーに割り当てられているが、個人的には使いにくいので別のキーをPrefixに割り当てたい。

~/.tmux.confに以下のように設定すると、プレフィックスキーを Ctrl + t に変更できる。

set -g prefix C-t

cliモードで動かすEmacsで、選択した範囲のテキストをmacosのクリップボードに持ってくる

Emacsを使うときに自分はcliモードで動かすのですが、そのままだとEmacs上のコマンドでテキストを範囲選択 + コピーしても、そのテキストをmacosクリップボードには反映されません。 Emacs上でコピーしたテキストはEmacs上だけでそのテキストをペーストできます。

ただEmacsで見ているテキストを他のアプリ(ブラウザ)などに持っていきたいときはmacosクリップボードに保存しておきたいので、その時は以下のコマンドを実行します。

M-| + pbcopy RET

前はEmasc上でテキストコピーしたときに自動でmacosクリップボードにも持っていくようにする設定を入れていたが、その設定が壊れたのでこの手法に変更。

参考

emacs.stackexchange.com

社内ドキュメントをひたすら読む

転職してから2週間、研修やアサインされたタスクの他に自分で意識して取り組んでいたのが「社内ドキュメントをひたすら読む」ということ。

社内ドキュメントが指すのは、Google Driveの共有ドライブに保存されている各種資料や開発チームで利用しているWIKI、タスク管理のツールのチケットなど。

この作業に取り組んでいる理由は以下である。

  • 誰がどんな情報を持っているのかを把握する
  • ドキュメントになっている情報と人から取るしかない情報を把握する
  • 会社の文化、現状の課題を把握する

誰がどんな情報を持っているのかを把握する

会社に入社したばかりだと、誰がどんなことをできる人でどんな情報を持っている人なのかわからない。

そこで社内ドキュメントをひたすら多読(タイトルと目次だけ見て、興味があるのだけ本文も読む)していると、アーキテクチャについて詳しい人、Rubyについて詳しい人、フロントエンドに詳しい人、ドメイン知識について詳しい人などがだいたい把握できてくる。

誰が何について詳しいかを知れば、困ったときにその人に質問すれば良いと分かるので仕事を進める上でスムーズなコミュニケーションができる。

ドキュメントになっている情報と人から取るしかない情報を把握する

いまコロナの影響もあって完全なリモートワークで自分は仕事をしているのですが、そこで課題となるのが必要な情報をどうスムーズに得るかということ。

そこで社内ドキュメントツールやGoogleDriveのディレクトリ構成を把握し、そこにあるドキュメントをタイトルだけでも軽く見ておくと、いまの時点でどんな情報がドキュメント化されていてどんな情報はされていないかの大体の予測がつくようになる。また予測がつかなくても大体この検索ワードとこのディレクトリを見てなければ人に聞くしかないと判断することもできる。

会社の文化、現状の課題を把握する

急成長中のスタートアップというのは、文化と課題のカタマリだと僕は理解している。

いままで行ったプロジェクトや会社にどんな課題があるかなどを、議事録や全体会でこれまで共有された資料などから把握することができ、そこでどんな議論と意思決定がされたのか読むことで会社の中でどんな文化が育っているのかを把握することができる。

現状の課題を理解することで、自分がどんなことをどのようなスピード感でやらないといけないか考えることができる。

文化というのは本来一緒に仕事を進める上で段々と染み込んでいくものだが、リモートワークであることでリアルでの接点が少なくどうしても文化を染み込ませるスピードが遅くなるという危機感があったので、まずドキュメントという接点に多く触れることでそこから文化を理解しようと努めていた。

今の会社では、週一で各部署の進捗報告を行う全社会、4半期ごとの振り返りを行う全社会があり、その資料や録画の映像がGoogleDriveに残っていたおかげで3ヶ月前や半年前の状況がだいたい把握できて「じゃあこれから自分は何をすべきなのか」を考えることがやりやすくなった。

最終的には人

ほんとに重要な情報というのはどんなドキュメントを整備しても、最終的には人が持っている事が多い。

今回「ドキュメントをひたすら読む」を行ったのは、すべてをドキュメントから読み取ろうとするのではなく、人から情報を得るための足がかりをまず得るというのが大きな目的で行っていた。

一旦ドキュメントをひらすら読むことによって会社に対する解像度も上がってきたので、これを元により多くの人とコミュニケーションをとって価値ある仕事でできるようにしていきたい。

2020年8月1日をもって、PaykeからCBcloudに転職しました

2020年8月1日をもって、約3年半ほど在籍していましたPaykeから、CBcloud(シービークラウド)に転職しました。

琉球インタラクティブ→Payke→CBcloudとキャリアとしてはこれで3社目になります。

CBcloudとはどういう会社?

東京に本社を持つ、物流業界の課題解決を目指したスタートアップです。

サービスは、荷物を運んでほしい人と運んでくれる運送ドライバーをマッチングするプラットフォームである「PickGo」、宅配業者の業務を効率化するシステム「SmaRyu Post」、運送業者向けの業務支援システム「SmaRyu Truck」、運送ドライバーさんにアプリで買い物代行を依頼できる「PickGo 買い物代行」など様々なサービスを提供しています。

cb-cloud.com

なぜCBcloudに転職したの?

転職を決めた理由はいくつかありますが、大きな点は以下の3つになります。

  • CBcloudが沖縄支社を立ち上げた
  • 物流というニーズが大きくかつ課題も深い産業
  • 強そうな人たちがいっぱいいる

CBcloudが沖縄支社を立ち上げた

2020年4月1日に沖縄支社を設立しました。

https://cb-cloud.com/news/Xo3I-hUAAIP3C3gb

僕も妻も沖縄で生まれ育ち両親も沖縄もいるため、生活の拠点として子育てする上で一番沖縄がいいと考えています。 しかし僕はソフトウェアエンジニアとして「つよつよになりたい!」ですし、より変化と成長が早い環境が好きだと思っています。 なので、キャリアの選択として常に「沖縄がソフトウェアエンジニアにとって、そして変化や成長の早い環境が好きな人にとって最高の場所になることに貢献できるか?」を考えています。

CBcloudを通して物流というすべての人のためのインフラの大きな課題解決に貢献し、沖縄支社をその課題解決のための重要な拠点として成長させることに貢献できれば、結果的に「沖縄でソフトウェアエンジニアにとって、そして変化や成長の早い環境が好きな人にとって最高の場所」の一つを作れることができると考えました。

CBcloudは社長が沖縄出身であり、かつプログラミングもできるエンジニアでもあるので、面談の時にも「沖縄にいる優秀なエンジニアが東京に行かなくてもやりがいがある仕事ができるようにしたい」という話をしてくれて、沖縄に対する想いは同じようなモノを持っていると感じました。

物流というニーズが大きくかつ課題も深い産業

日本の物流というのは、社会のインフラであり、これからも非常に早いペースでニーズが増えているにも関わらず、深刻なドライバー不足という大きな課題を抱えています。

ドライバー不足の原因は、収入の不安定さや労働環境の過酷さなど多数あります。

CBcloudは「ドライバーファースト」の理念を掲げ、ドライバーと荷主をマッチングするプラットフォームによる「仕事の選びやすさ」や「仕事の安定的な供給」を提供、SmaRyu PostやSmaRyu Truckなどでドライバーの複雑な仕事を誰でも簡単に行えるようにするシステムを提供することで「効率化」や「ドライバー業務の参加しやすさ」を作り出し、ドライバーという仕事をより価値の高いものにしようとしていて、非常にやりがいのある仕事だと思いました。

また、最近の僕のエンジニアとしての理想像として「特定の業界への深い理解 x ソフトウェアエンジニアリングの高い技術力」というものをイメージしています。 業界への知識が浅くてよく、技術力だけ解決可能な課題というのはGAFAMが最終的には持っていける市場だと考えていますが、業界に深い知識を持ちかつ深く入り込んで地道にネットワーク作ることによってやっと解決できるような課題はGAFAMでもなかなか取れません。

その点CBcloudはANA Cargoが提供する空港間配送との連携をPickGoに取り入れることによって、ドライバーさんとのマッチングだけでは達成できなかった長距離配送の低価格と配送スピードを実現しており、見ていて「すごいかっこいいな!」と思いました。

僕自身もまずはソフトウェアエンジニアとしての価値を出しつつも、ゆくゆくは物流という業界への深い理解とネットワークを作って、技術だけでは解決できないような課題さえ解決できるようになりたいと考えたのも理由の一つです。

強そうな人がいっぱいいる

面談を通して出会った方々、そしてCBcloudに関わってそうな人をSNSなどで探して観察してみても、エンジニアもそうでない人も非常に優秀そうな方々ばかりでした。

自分の成長というのは周りにどんな人がいるか決まると思っているので、自分よりもはるかに優秀な人がいる、そしてそんな人たちが集まってくるような環境に常に身を置きたいと考えていて、その環境がCBcloudには確実にあると感じたのも決め手の一つです。

CBcloudでなにをやるの?

今の所、まずはサーバーサイドの開発とクラウドインフラの設計・改善・運用あたりをしていくことになるだろうと思っています。 PaykeではPHP + Azureでしたが、CBcloudではメインがRuby + AWSになりそうです。 Azureは好きなのでいま開発している個人プロダクトはAzureを使ってキャッチアップはそれを通して続けつつ、もしAzureの方が最適なユースケースがあればCBcloudでも採用できるようにしておきたいなーと個人的には思っています。

また沖縄支社の最初のエンジニアということもありますので、エンジニア組織を作るための採用活動なども積極的に行って行きたいと思います。 興味のある方がいらっしゃいましたらお気軽にお声がけください!

個人的な野望として、沖縄から日本、そして世界に使われるようなCBcloudの新たなプロダクトを生み出し育てたいとも思っているので、そのチャンスは常に探って行きたいと思っています。

さいごに

CBcloudのオンラインミートアップがあります!

沖縄支社ではカスタマーサポートとエンジニアの採用を行っていますので、もし少しでも興味のある方は以下のWantedlyの記事からお気軽にご参加くださーい!

エンジニア向けはこちら

www.wantedly.com

カスタマーサポート向けはこちら

www.wantedly.com

Clojure/leiningenでユニットテストを実行する

leiningenを使っているプロジェクトで、ユニットテストを実行する方法について整理します。

ユニットテストを実行する

$ lein test

特定のnamespaceのユニットテストだけ実行する

$ lein test sample-app.core-test

テストをメタキーワードでグルーピングして、そのグループのテストだけを実行する

project.cljにtest-selectorsを追加する

 .
 .
 :test-selectors {:api :api
                  :model :model
                  :core :core)}
 .

テストコードにキーワードを指定する

 (ns ^:core sample-app.core-test
    (require [clojure.test :refer :all]
        [sample-app.core :refer :all]))
 
 (deftest ^:api a-test
    (testing "TEST A" 
        (is (= 1 (+ 1 1)))))
        
  (deftest ^:model b-test
    (testing "TEST B" 
        (is (= 1 (- 2 1)))))

キーワードを指定して lein testを実行する

# :modelメタキーワードが設定されたb-testだけ実行
$ lein test :model 
 
# :apiメタキーワードが設定されたa-testだけ実行
$ lein test :api
 
# :coreメタキーワードが設定されたsample-app.core-testに含まれるa-testとb-testが実行される
$ lein test :core

特定の関数だけテストする

$ lein test :only sample-app.core-test/a-test

フロントエンド開発における課題を問い直す〜2020年6月版〜

2020年6月21日(日)「チャリティカンファレンス沖縄2020 Vol.1 Frontend編」というイベントで、「フロントエンド開発における課題を問い直す」というタイトルで登壇させていただきました。

re-build.connpass.com

f:id:arakaji-yuu:20200625152514p:plain
フロントエンド開発における課題を問い直す

今回発表資料の準備をするにあたって、まず話したいことをテキストでひたすら書いていき、全て書ききったらそれをもとにパワポのスライドに情報を圧縮するというアプローチで作っていたのですが、せっかく書いたテキストをそのまま捨てるのはもったいないので多少加筆修正した上でこちらのブログにて公開することにしました。

このイベントに参加出来なかった人にも登壇内容が届いて、なにかの参考になれば幸いです。


フロントエンド開発における課題を問い直す〜2020年6月版〜

speakerdeck.com

なぜこのテーマを選んだか?

登壇すること自体は1ヶ月以上前から決まっていたのですが、登壇テーマがなかなか決まらずグズグズしていると当日のスケジュールが発表されました。 それを見てみると自分がトップバッターの一人になっていて、かつKey noteという立て付けになっているので、これはやばいぞと思いました笑

せっかくKey noteという立場をいただけたので、僕の方では特定の技術トピックについてお話するのではなく、現在のフロントエンド開発の全体像が見えるようなお話をして、それから他のセッションを聞いて深堀りをできるような形にしていきたいと思います。

では全体像をどういう視点で見ていくかという話なんですが、現在のフロントエンド開発は様々な技術が出てきており、それらはすべて開発における課題を解決するために生まれています。

僕もエンジニアとして技術を学ぶときに「この技術がおもしろそう!!→この技術はこの課題を解決するために生まれたのか〜」というテクノロジーファーストなきっかけで学ぶ事が多いのですが、本質的にはまず課題があり、その課題に対して技術でどう解決するかという、イシューファーストなアプローチを取るべきです。

そのため本セッションでは、まずフロントエンド開発における課題を改めて問い直して整理し、その課題に対していまどういう技術が解として存在するのかという話をしていきたいと思います。

課題の定義

ではフロントエンド開発における課題はこれです!という話をする前に、まず課題というのがどこから生まれるのかという話をさらっとしておきたいです。

国語辞典で「課題」と調べると以下のようにでます。

1 与える、または、与えられる題目や主題。
2 解決しなければならない問題。果たすべき仕事。

「解決しなければならない問題」というのはわかりやすい定義ですね。じゃあフロントエンド開発における解決しなければならない問題っていうのはなぜ解決しないといけないのか?

これを僕は、 「進みたい方向に進みたい速度で進みたいが、それが出来ない障害があるので、解決しないといけない」と考えています。

そう考えるとまず課題を知るにはそもそもの進みたい方向というのを知る必要があることがわかります。

フロントエンド開発の目的はユーザーにより良いUXを届けること

進みたい方向というのは、フロントエンド開発における目的になります。 フロントエンドというのは、システムとユーザーが接する部分のUIであり、その目的は良いUXを提供することになります。 じゃあ良いUXってなにか?という話になるんですが、UXの品質評価方法のひとつとして、UXハニカムという手法があります。

blog.btrax.com

これはプロダクトやサービスが提供するUXの評価軸を、useful、desirable、accessible、credible、findable、usableの6つの項目に分け、それぞれの項目を5段階評価をし、その総合点でUXを評価するという手法です。

各項目は以下の様に定義されています。

1. Useful – 役に立つ 提供されるプロダクトやサービスがユーザーの役に立っているか。彼らのニーズを満たしているか。もしそれがユーザーの目的を達成していなければ、ユーザー体験としてはレベルが低い。

2. Desirable – 好ましい プロダクトの見た目や雰囲気がユーザーにとって好ましいかどうか。ここに評価軸においては”デザイン要素”はなるべく少ない方が優れているとされる。

3. Accessible – アクセスしやすい 体の不自由な方や、異なる制限のあるユーザーにとっても使いやすい体験がデザインされているかどうか。色盲の方でも認識しやすいサインなどもその例の一つ。

4. Credible – 信頼できる 企業やプロダクトが信頼できるものであるかどうか。例えば無名な企業よりも、著名なブランドの製品であれば、最初からユーザーの心理的ハードルが下がり、自ずと利用体験がよくなりがち。

5. Findable – 探しやすい 情報やコンテンツが見つけやすい。短期間でユーザーが求める情報にたどり着ければ、利用している際のストレスが下がる。サイトであればページの構造、駅や公共の建物であれば、目的の場所に辿り着きやすいなど。

6. Usable – 使いやすい そしてユーザビリティの高さ。利用していて必要以上に複雑で使いにくい場合はユーザー体験の価値が下がってしまう。例えば家電製品であれば、説明書を読まなければ使い方がわからない時点で減点対象になるであろう。

つまり、UXを最大化させることがUI/フロントエンド開発における目的であるならば、これら6つを高めようとすると発生する課題がフロントエンド開発における課題となります。

では、やっと本題です。フロントエンド開発をすると発生する課題とはなんでしょうか?

正解がわからない

最も大きな課題の一つはUXの6つの指標を高めるためにどうすれば良いという正解が誰にもわからないことです。自分たちがリリースしたプロダクトが本当にユーザーの役に立つのか、使いやすいのか、ユーザーに好んでもらえるのかということは、実際にリリースして反応を見てみるまでわかりません。

マルチデバイスへの対応

ソフトウェアのUIは、10数年前まではPCでの利用のみを対象にしていればよかったのですが、現代ではPCだけでなく、スマートフォンタブレットの利用まで対象にしないといけません。そしてそれぞれのデバイスのOSの違いや、スペックの違い、利用シーンでのネットワーク環境の違いなど様々な状況を考慮に入れた開発をしていく必要があります。

ユーザーの期待値の増加

スマートフォンの普及によって、一般の人もアプリという形でソフトウェアを日常で使うことが普通なことになってきました。そしてみんなが使っているものといえば、instagramTiktokNetflixなど世界No1を取ったものばかりです。その世界トップレベルに洗練されたプロダクトを日常で使い目が肥えたユーザーに、それよりも劣るUXを提供してしまってはなかなか使ってもらう、使い続けてもらうに至るのは難しいでしょう。 つまりUXにおいては、資本力においてはるかに劣っていながらも、必然的に世界トップレベルのサービスの基準と戦うことが宿命付けられています。 またスマホアプリと接する時間が増えることで、スマホでWebアプリを使う時に関してもスマホアプリと同等のUXが求められるようになってきました。

正解がわからないという課題に立ち向かう手段

正解がわからないという課題に対して立ち向かうには基本的には「早く小さくリリースして、フィードバックを得て、そのフィードバックをもとにまた早く小さくリリースする」を繰り返すしかありません。これがいま良く言われているアジャイル開発で行われていることでもあります。 では、みんながアジャイル開発をしている時代においてチーム力、開発力として差がでるところは以下の点になります。

  • 単位時間あたりの試行回数を増やせるか?
  • データドリブンな意思決定を行う

単位時間あたりの試行回数を増やす

  • 限られた人数での開発効率を上げる
  • コード量が増えても開発効率を落とさないようにする
  • 人数が増えても開発効率を落とさないようにする

データドリブンな意思決定を行う

  • ユーザーの利用動向に関するデータ収集
  • データの可視化

では、上記を行うためにいまどのような技術がソリューションとして存在するのか?

Firebaseはフロントエンドエンジニアの必修項目のひとつ

「単位時間あたりの試行回数を増やす」、「データドリブンな意思決定を行う」のための手段を総合的に、かつ非常に低価格、そして簡単な方法で提供しているサービスは僕の知る限りFirebaseにおいてありません。

Firebaseのすべての機能を必ず使う必要はありませんが、Firebaseで何が出来て何ができないのかを把握して戦略を持って利用することができれば大きな武器になる、というよりもむしろ戦略を持って利用できないために不要なコストを書けて開発しなくてもよいものに開発リソースをかけてしまい競合に遅れを取るということにことになりかねません。

単位時間あたりの試行回数を増やすことにどう貢献するのか?

「単位時間あたりの試行回数を増やす」ために、限られた人数での開発効率をあげる、コード量が増えても開発効率を落とさない、人数が増えても開発効率を落とさない、という3つの点が重要です。

この3つの課題を同時に解消するための手段は、「自分たちで作らない部分を増やすこと」です。

Firebase AuthenticationというFirebaseが提供する認証サービスを例に考えてみましょう。

firebase.google.com

ユーザー認証の部分を自分たちでスクラッチで作らずにFirebase Authenticationを使うという戦略を取れば、その開発コストが大幅に減少し、その分他のアプリ固有の価値を生む機能や改善に開発リソースを使うことができ、それによって開発効率が向上します。

認証機能を自分たちで全て書くよりもFirebase Authenticationを使う方がコード量ははるかに小さくなるため、開発効率を落とさないで済むことができます。

人数が増えると仕様のキャッチアップをするためのコミュケーションコスト増加によって開発効率が落ちていくのですが、自前で作らずFirebase Authenticationを使う選択をしたことで仕様のキャッチアップはFirebase自体のドキュメントを読むだけで完了します。

もちろん外部サービスを利用する場合はそのサービスで出来ないことは出来ないこと、そしてそのサービスの提供が終了してしまうリスクなども考慮した上で利用を検討するべきですが、自前で作らずに既存のサービスを利用することで作らないモノを増やすことは開発効率を上げるための強力な手段になります。

Firebase Authenticationは認証というアプリ必要な単機能を提供してくれるものですが、もっと大胆に「作らない部分を増やす」ことに貢献するFirebaseのサービスがCloud Firestoreです。

Cloud Firestoreはクラウド上でホスティングされたNoSQLデータベースですが、iOSアプリ、Androidアプリ、WebのフロントエンドなどのクライアントからSDK経由で直接アクセスできるという特徴があります。

さらにリアルタイムアップデートという機能によって各デバイスから更新されたデータがリアルタイムで各デバイスに共有される機能、オフラインサポート、スケーラビリティの高さという特徴もかねそ兼ね備えています。

コレをうまく活用すれば、いままで単純なデータの読み書きだけのために行っていたサーバーサイドのAPI開発やデータ同期のためのプログラム、そしてスケーラビリティ確保のためのインフラ運用などの大部分を省く事が可能になります。

こちらも利用することによるトレードオフを見越した上で戦略を立てるべきですので、開発効率を上げるための自分の手札として何が出来て何ができないのかをしっかりとキャッチアップしておくべきでしょう。

データドリブンな意思決定を行うことにいかに貢献するのか?

開発効率をどれだけ高める事ができても、提供した機能がユーザーの体験価値をちゃんと高めたのか、またいま提供しているプロダクトのどこがユーザーの体験価値を毀損しているのかを把握することが出来なければ、正しい方向にプロダクトを改善していくことができません。

正しい方向にプロダクトを改善していくには、「ユーザーの利用動向をデータとして取得する」「取得したデータを可視化する」という2つが非常に重要です。

この点においてもFirebaseはGoogle Analyticsという強力なツールを提供しています。

firebase.google.com

Google AnalyticsSDKを入れるだけで、自分たちのアプリをどれくらいのユーザーが利用しているのか、どこで利用しているのか、どれくらいの時間利用しているのかなどがわかります。

より詳細なことが知りたい、たとえばどの画面を開いたのか、どのボタンを押したかなどを知りたければイベントを発火するコードを書くだけでクラウド上に記録されていきます。

そしてそれらのデータがGoogle Anaticsのダッシュボード上で可視化されるので、そのダッシュボード上で自分たちのアプリが正しく改善されているのかを客観的な事実であるデータで知る事ができます。

同じ事ができるツールは他にもありますがそれらは有償であることや、Firebaseの場合他にもパフォーマンス監視やクラッシュレポートに関する機能なども提供されかつ無料であることを考えても、デフォルトで取る選択肢としてFirebaseのGoogle Analyticsを利用することが多いでしょう。

「単位時間あたりの試行回数を増やす」、「データドリブンな意思決定をする」をするための強力な技術の一つとしてFirebaseがあるのは間違いないため、これからフロントエンド開発に関わる上でほぼ必須科目に近いぐらい身に付けないといけないモノだと考えています。

マルチデバイスへの対応という課題に立ち向かう手段

マルチデバイスへの対応というのはまず2つに分類することができます。

  • Webのフロントエンドをマルチデバイス対応をどうするのか
  • 各デバイスのネイティブアプリを提供をどうするのか

今回は「Webのフロントエンドをマルチデバイス対応すること」は、僕の理解だとどこもそこまで大きなインパクトのある差異はなくて「レスポンシブ対応していこうな」というところだと思っています。

各デバイスのネイティブアプリを提供するかどうかという点は、今回はわかりやすくするため以下の3つのプラットフォーム上に、それぞれ用のフロントエンド(モバイルの場合はネイティブアプリ)の提供をどのようにするのか?という風に考えます。

これは「それぞれのプラットフォーム上のアプリ同士でどのくらいコードを共有するのか?」を考えることです。

単純に考えると、すべてのデバイスにそれぞれのプラットフォーム用のプログラミング言語(AndroidJavaiOSをSwift、WebをJS)でフロントエンドを書くことにした場合、すべてのプラットフォーム用に共通コードを使うよりも開発リソースが必要になります。

しかし、コードをすべて共通化した場合には各プラットフォーム固有の処理を書かなければならない場合にはコードを分離して書かなければならないためコードの複雑性は高くなる傾向があります。またプラットフォーム間のコード共通化を支援しているフレームワークが、各プラットフォームのアップデートにどれだけついていけるのか?という課題もあります。

これらのトレードオフを見極めた上で技術選択をしていく必要がありますが、ではこの課題に向き合うための技術はなにがあるでしょうか?

Flutter、iOSAndroidのコード共通化の解のひとつ

FlutterはGoogleが提供しているiOSAndroidアプリをDartという言語で、共通のプログラムで書く事ができる技術の一つです。

flutter.dev

ただし共通化できるのはあくまでUIとビジネスロジックなどプラットフォームに依存しないコードの部分であり、カメラなどの機能はプラットフォーム固有のコードをプラグインという形で書く必要があります。ただ良く使う機能のほとんどはOSSプラグインが提供されているので凝ったことをしないのであればそれをインストールして使うことで解決するでしょう。

今回のカンファレンスでは登壇者がいませんが、iOSAndroidでコードを共通化するというアプローチを取っている技術はFlutter以外にもあります。

・Xamarin ・React Native ・ionic(cordova)

Xamarin

XamarinはMicrosoftが提供するフレームワークで、C#という言語を使ってiOSAndroidアプリを開発することができます。先日公開されたCOVID-19の接触確認アプリも、実はXamarinで作られています。もしインストールしていない方がいればぜひインストールしてみてください。

docs.microsoft.com

XamarinとFlutterの違いとして特徴的なのが、Flutterは「UIとロジックの共通化が目的」なのに対して、Xamarinは「ロジックの共通化が目的、だけどUIも共通化をしたければできる」という違いです。

Xamarinは、AnroidやiOSの各プラットフォーム固有のAPIC#APIで1対1のマッピングを行っているので、C#から直接プラットフォーム固有の機能を使うことができます。 Xamarin.Formというライブラリを使うとiOSAndroidで共通コードを使ってUIを作ることもできますが、全く別々のコードを使いつつロジックだけ共通化するというアプローチも取れます。

React Native

こちらはReact.jsというWeb用のViewライブラリをiOSAndroidでも同じ思想で使えるようにしたものです。こちらはJSを使ってiOSAndroidのUIとロジックを共通化して作ることができます。

reactnative.dev

JSでUIを書くにも関わらず実際に実行されているのはネイティブのUIコンポーネントなので、ネイティブアプリ水準のパフォーマンスが期待できます。

FlutterやXamarinとの違いは、すでにウェブのフロントエンドを作るのと同じReact.jsとJavaScriptをネイティブアプリの開発利用できるようにすることで、Webのフロントエンド開発者を、学習コストを減らした形でモバイルのネイティブアプリの開発者として転用可能にしている点です。

ionic(cordova)

ionicはFlutter、Xamarin、React Nativeと違い、JS/HTML/CSSというWebのフロントエンド技術を使ってアプリを作り、それをモバイルアプリのWebView上で動かすというアプローチを取っています。

ionicframework.com

これはiOSAndroidでコードを共通化するのはもちろんのこと、Webフロントエンドともコードを共通化することが技術的には可能になります。(Webと共通化する場合ネイティブの機能を提供するPluginをどううまく扱うか、またWebとモバイルアプリで製品のライフサイクルが違うなどの課題はある)

そのトレードオフとして、パフォーマンスやUXの面でネイティブアプリ同等のものを提供する難易度が高い、プラットフォーム固有の機能を使う場合はpluginという形で別でコードを書かなければならないなどの課題も出てきます。

このようにAndroidiOSのコードを共通化してマルチデバイス対応を開発効率を上げながら行うための技術はいくつかあります。 各ツールのメリットデメリットを理解しつつ、共通化するのか別々に作るのか、また共通化するならどの部分を共通化するためにどのツールを使うのかを考えて選択していく必要があります。

ネイティブアプリを使わずにWebアプリをモバイルアプリのように提供する方法としてのPWA

FlutterやXamarinなどはあくまでAndroidiOSでコードを共有してモバイルアプリを開発・提供するための技術ですが、あくまでウェブアプリとは別のコードを書く必要があります。

そこに対して「ウェブアプリ自体をモバイルアプリのように動かせるようにしたらいいじゃないか」というアプローチを取っているのがPWA(Progressive Web App)の技術になります。

developer.mozilla.org

PWAとはReactやFlutterのような特定のフレームワーク、ライブラリのことではなく、ブラウザに搭載されている機能の組み合わせによってモバイルアプリと同等の機能を実現するためのデザインパターンのようなものです。

ここでいう「モバイルアプリ同等の機能」とは、以下になります。

  • インストール可能(ホーム画面にアイコン設置、そのアイコンをタップして起動できる)
  • ネットワーク非依存(ネットがなくてもローカルにデータ保存して動かすことができる)
  • 再エンゲージ可能(プッシュ通知など)

モバイルデバイスに大きく依存した機能(カメラやGPS、ARなど)が必要なアプリについてはPWAのアプローチは取れないですが、Webで提供している機能をモバイルでも提供したいだけの場合、PWAのアプローチを取ることでモバイルアプリの開発リソースを全く使わずに上記3つの要件を実現することが可能になります。

ユーザーの期待値の増加に立ち向かう手段として生まれたSPA

スマホネイティブアプリと同等のUXをWebのフロントエンドでも実現するために考え出されたのがSPA(Single Page Application)です。

皆さんご存知だと思いますが、SPAは1ページのHTMLをJSで動的に書きながら画面描画をする技術のことです。

いままでは画面遷移やユーザーのアクションのたびに画面を全部リロードしないといけなかったものを、必要なデータだけをサーバーと通信し画面描画はリロードせずに行えるようにすることでスマホアプリのようなUXを実現可能にしました。

SPAによってネイティブアプリとUXで戦える土台を手に入れましたが、それによってまた新たな多くの課題を生み出しました。それが以下になります。

  • JSでより多くを担当することによるプログラムの複雑性が増加
  • 初回表示パフォーマンス悪化とGoogleインデックスが遅い問題

プログラムの複雑性の増加

画面描画処理の複雑性とパフォーマンス改善

SPA以前は入力フォームのバリデーションや少しのAJaxやHTMLの動的変更程度だったJavaScriptの役割が、SPAによって非常に多くのことを担当せざる得なくなり、それによってコード量の増加、複雑性の増加が激しくなりました。

そのうち最も大きな比重を占めるのが、アプリケーションの現在の状態をもとに画面を正しく描画する、DOMを変更するというプログラムを書くことです。

この処理を、メンテナンスしやすく、簡単に、かつパフォーマンス高く解決しようと生まれたのがReact.jsであり、Vue.jsであり、Angular(js)になります。

不具合発生率を言語レベルで減らすための策としてのTypeScript

SPAにすることで画面描画処理の他にも非常に多くのロジックがプログラムに入ってきてコード量がふえてきます。コード量が増えてくると適切に設計されていなければ依存がどんどん増えていき、一つの変更によって想定外の場所に影響が及びバグが発生してしまう可能性も高くなります。

バグをリリース前に見つけるにはテストが必要ですが、手動テストでは時間が非常にかかってしまう上に漏れの可能性もあります。そのため本来的には自動テストを書くべきではあるのですが、UIに関するテストはテストプログラムを書く難易度が高い上にUIの変更頻度も多いため書いたプログラムが無駄になることも多々あります。

このトレードオフに関するリーズナブルな解としてTypeScriptが利用されるケースが増えています。

TypeScriptはJavaScriptにトランスパイルすることができる言語ですが、JavaScriptに型という言語仕様をつけているのが一番の特徴です。

関数や変数で受け取れる値の型を明示することで、間違った型の値が入った場合にはコンパイル時にエラーを検出してくれます。

これにより、値の形式(型)違いによるバグの発生を事前に防ぐ事ができる上に、不要になったコードの削除や簡単なプログラムの変更などをコンパイルが通ればある程度は動くという安心感を得られるようになりました。

もちろんテストを置き換えるものではありませんが、コードや開発に関わる人が増えていったときにも開発効率を下げないための手段としてTypeScriptはJavaScriptをそのまま使うよりは支持されているように思えます。

初回表示パフォーマンス悪化とGoogleインデックスが遅い問題

SPAによって、Webアプリを利用中のUX/パフォーマンスは以前と比べて大きく改善可能になりましたが、逆に初回表示時のサーバーからレスポンスを受け取ってから画面が描画されアプリを利用できるようになるまでのパフォーマンスの悪化が問題視されるようになりました。

SPA以前の場合はサーバー側でHTMLを描画しているため、そのレスポンスをブラウザが受け取って描画するまでの時間は微微たるものでした。

しかしSPAになるとサーバーからのレスポンスは早くても、そのレスポンスをブラウザが受け取って画面を描画するためにはまずJavaScriptをすべて読みこんで解釈し、それを実行し、それからAjaxで画面描画のためのデータを取得とし、最終的に画面が描画されるため初回表示時の待ち時間が明らかに悪化していました。

また、Newsなどのメディアサイトの場合Google検索からの流入が非常に多いため、Googleに正しくそして早くインデックスされることがビジネス上非常に重要なファクターになるのですが、GoogleクローラーはJSの解釈は行うためSPAで作ったサイトでもインデックス自体はされるものの、JSの解釈をしてインデックスをされるまでの時間が通常のサイトよりも遅くなる傾向があるため、この問題も解決する必要がありました。

初回表示パフォーマンス悪化とGoogleインデックス遅い問題を両方解決するためのアプローチとして生まれたのがSSR(サーバーサイドレンダリング)という技術です。

SSRとは、SPAの場合はクライアントサイドで描画していたHTMLを、初回表示の場合のみサーバー側で描画しつつ、クライアントでJSが実行された際には現在の状態をHTMLから読み取れるようにデータを埋め込んでおく手法です。

これにより初回表示の場合はJSの実行またずに画面描画されつつ次のユーザーのアクションからはSPAとしてJSで画面描画を行うことを可能にしました。 初回表示をサーバーサイドでHTML描画できるようにしたことで、GoogleクローラもJSの実行なしにコンテンツを読み取れ、早くインデックスされることを可能にしました。

しかしこのSSR、フロントエンド用に書いてあるJSをサーバーサイドのnodejsで実行できるようにしつつ状態の受け渡しをスムーズに行う必要があるため、0からコレを作るのは非常に手間のかかるものでした。

それをSPAでよく使われるViewライブラリ毎にフレームワークとして解決したのが、Vue.jsのNuxt.jsであり、React.jsのNext.jsです。ちなみにAngularの方もAngular UniveralというAngularに同梱されているライブラリでSSRの導入をできるようにしています。

さいごに

この7〜8年のフロントエンドに関わる技術の発展は凄まじく、いろんな技術が生まれては消えていきます。しかし、それらの技術はいずれも特定の課題に対する解決策として生まれています。

ただいま流行っている技術を追うだけでなく、そもそもいまフロントエンド開発に起こっているトップレベルの課題からブレイクダウンして課題を具体化し、それらの解決策としていま注目されている技術はどのようにマッピングされているのかを見ていくと、自分たちのプロダクトや組織にとって必要な技術がなんなのかが見えてくると思います。

この発表で、いまのフロントエンド開発のなんとなく全体像が見えてくる、かつ、課題から考えるということの重要性を理解することが出来たら良いなと思っています。

長々とお付き合いいただきありがとうございました。

D2Cの本質を考える

D2Cの本質を理解する

いま「D2C」というのがバズワード化しているが、それが意味するのはECサイトでメーカーが直接顧客に商品を売るというだけものではない。このドキュメントでは、D2Cとして表現されている企業が伝統的なメーカーよりも非常に早い成長を遂げた重要な成長ドライバーはなんなのか?そして既存のメーカーがD2Cから得られる知見を生かしどのような戦略を実施するべきなのかを考えてみる。

D2Cとは

まずD2Cという言葉の定義を揃えておく必要がある。D2Cとは、メーカーが消費者へ直接商品を販売することだけを意味する言葉ではない。

D2C 「世界観」と「テクノロジー」で勝つブランド戦略」によると、D2Cの辞書的な定義は以下になる。

新しい消費の価値観を持つミレニアル世代以下のターゲットに対し、ユニークな世界観を下敷きにしたプロダクトとカスタマーエクスペリエンス、SNSや店舗を通じた顧客とのダイレクトな対話、垂直統合したサプライチェーンを武器に、VCから資金調達を行い、短期間に急成長を目指すデジタル&データドリブンなライフスタイルブランド

つまりD2Cブランドは以下のような特徴を持っていることを意味する。

  • 顧客ターゲットがミレニアル世代
  • チャネルが直接販売、
  • コミュニケーションチャネルがSNSなどのデジタルを使った顧客との直接コミュニケーション
  • 成長速度が指数関数的な急成長
  • デジタル技術を駆使したデータドリブンな意思決定とオペレーションの改善
  • 商品の機能ではなく、世界観(ブランド)を通した総合的な体験価値を提供する

なぜいまD2Cが注目されているのか

Casperという2014年に登場したマットレスを販売するスタートアップが、急速に成長し伝統的なマットレスメーカーのシェアを奪っていく。創業初月に1億円、最初の12ヶ月で100億円、2年目には200億円に到達。2019年はじめには北米地域だけで200もの店舗を出すことに成功している。

Casper以外にもメガネ業界ではWarby Parker、スーツケースブランドのAwayなどが登場し、それらがインターネット企業のスタートアップのような急成長を行うことに成功し、ユニコーン企業(評価額が1000億円を超えるベンチャー企業)になったことから、これらの企業に共通する特徴をD2Cというワードにまとめて注目されることとなった。

なぜミレニアム世代をターゲットとするのか

ミレニアム世代とは

ミレニアム世代とは、アメリカにおいて1980年代から1990年代後半までに生まれ、2000年代に成人または社会人になる世代のことを言います。この世代の特徴として、デジタル・ネイティブ、物心ついたときからPCやスマホ、インターネットなどが身近にある環境で育っているという点が挙げられている。

人口割合の巨大さ

アメリカ国内のミレニアル世代の人口は約9000万人にのぼり、ベビーブーマー世代を抜いて米国最大の年齢層になっただけでなく労働力人口に占める割合も最大となっている。

ミレニアル世代の労働力にしめる比率は2019年時点で35%だが、2030年までに75%に達すると予想されいる。それだけでなく、ミレニアル世代は推定30兆ドルの資産をベビーブーマー世代の親から相続すると予想されている。 また教育水準が最も高い世代とされており、学士号以上の比率は同じ年齢でみるとみれミレニアル世代が40%前後に対してX世代が29%、ベビーブーマー世代は25%となっている。

つまり、人口規模や若さ、高い教育水準、さらに巨額な相続資産により今後長年米国経済を牽引する消費者層と考えられており、D2Cの急成長は伝統的な企業がいままで提供できていなかったミレニアル世代に対する価値提供をうまく実現することが大きな成長ドライバーとなるため、ミレニアル世代をターゲットとしている理由の一つになると考えられる。

EC経由での購買ハードルの低さ

D2CはECでの直接販売がメインの販売チャネルであるため、 その成長速度は対象となるユーザーがEC経由でその商品を購入することのハードルが低いことに大きく依存する。

ミレニアル世代はデジタルネイティブと呼ばれ、物心ついたころからPC、インターネット、スマホなどに触れながら育ってきた世代のため、それよりも上の世代よりもECでの購買ハードルが低い傾向にある。

このEC経由での購買ハードルの低さもミレニアル世代をターゲットしている理由の一つといえるだろう。

なぜ直接販売をするのか

  • 卸や小売店に取られる中間マージンをなくすことでき、その分より低価格で販売することができる。
  • デジタル経由で顧客に直接販売することで、様々なデータを取ることができ、そのデータによってプロダクト自体や各種オペレーションを最適に、かつ素早く改善していくことができる。

なぜSNSなど通じた顧客との直接コミュニケーションを重視するのか

  • 直接コミュニケーションすることにより、エンゲージメントを高める手段を得ることができる
  • エンゲージメントを高めることで、ユーザー自身がブランドや商品を拡散するという現象を起こすことができ、それにより伝統的なメーカーよりも低コストでユーザーを獲得することができる(仮設)

なぜ指数関数的な急成長を実現できるのか

  • アメリカの場合はミレニアル世代が相当な人口ボリュームがあるのでターゲットとして成功した場合大きくスケールする
  • 各種データを取りながら改善を回す事が可能なため、最適化もしやすい。成功した場合の将来の成長性も計算しやすいためVCからの投資を集めやすい。

なぜデータドリブンな意思決定とオペレーションの改善が実現できるのか

  • ユーザーとの接点がソフトウェア上になっているため、各種データを取りやすい
  • またデータを元にしたオペレーション改善もソフトウェアで対応しやすい

なぜ機能ではなく世界観を通じた体験価値の提供を重視するのか

  • ミレニアル世代の特徴として、モノではなくコトの方を大事にする価値観をもっているため

D2Cの本質

本質的に重要なのは、価値あるデータをあつめ、それを分析し、データドリブンで高速にオペレーションを改善すること。そしてデータや顧客との直接的な対話から、顧客の持つより本質的な課題を見つけ、それを解決するプロダクトを正しく提供する、プロダクト自身も改善していくこと。そしてそのサイクルを高速に回すことである。

より価値あるデータを集める、顧客の本質的な課題を見つけるために、ソフトウェア(SNS、EC)を通して直接顧客との接点を持つ。

ミレニアル世代をターゲットとするのは、あくまでデジタル経由のコミュニケーションや購買行動のハードルが低い、かつアメリカにおいては非常に大きな人口割合を占めているからである。

機能ではなく世界観を通じた体験価値を提供しているのは、ミレニアル世代をターゲットするために必要だからである。

D2Cから学んで既存メーカーが取り組むべき戦略はなにか

D2Cでの成功例をみて、いきなりSNSをやる、ECをやるというのは違う。

重要なのは価値あるデータを集めること、データドリブンで意思決定し、高速にオペレーションや商品開発を改善していくことにある。

つまり既存メーカーがまず取り組むべきは、いま持っているまたは得られるデータを集め、分析し、それをもとに意思決定し、改善するというサイクルを回すこと。そのための土台を整えることである。

その土台をもとに既存事業のオペレーションや商品改善サイクルを回していき、成功体験を作ること。

その後、ミレニアル世代を中心とした顧客層と直接つながるための販売チャネル、コミュニケーションチャネルを確立し、そこで得たデータや顧客の課題をもとに新たな商品を作っていくという順番が正しいだろう。

参考