yusugiura
現地現物によるプログラミング勉強法
見出し画像

現地現物によるプログラミング勉強法

yusugiura

一般的に、プログラミングの勉強法といえば、参考書のコードを読んだり、実際にコードを書いたりするのが普通ですが、筆者の勉強法は少し特殊です。すでに世の中に公開されているwebサービスを、丹念に調べていくことで、プログラミング学習の糧にしているからです。その理由は、理想と現実の差分にあります。教科書には美しいコードや設計が書かれていますが、一方で現実のサービスは、必ずしも美しいとは限りません。webサービスは一つの商売である以上、ユーザーの要望に素早く応えなければならず、理想と現実の間で折り合いをつける必要があるからです。

そこで、今回は、公開されているサービスを事例に、現地現物によるプログラミング学習を実践します。当然、実際の企業で運営しているサービスのコードは「秘中の秘」であるため、パブリックにはなっていないものの、様々な事情で外部に公開されているコード(フロントエンドのJavascript)や、HTTPSで送受信されるAPIなどから、推測に基づく学習が可能です。今回は、公開情報として取得できる範囲から、システム設計の意図、そのサービスを運営する組織の狙い、ビジネスにおける投資の力点などを推測します。

画面遷移図を書いて全体像を見渡す

今回、題材にするサービスは「ネット生命保険」のサービスを提供するライフネット生命保険です。生命保険は申し込みに大量のフォーム入力が必要であり、当然離脱率も高いと推察されるため、どのように「離脱率を最小化するのか?」という知恵を学べることを期待して、選定しました。

まず最初に行うことは「画面遷移図」を書いて、ユーザーの導線を確認することです。画面遷移図とは、ユーザーに見える画面の遷移を書いたものになります。大抵の場合、実際のwebサービスは複雑怪奇なため、画面遷移は複雑になりますが、今回は勉強のためなので、最も重要な画面遷移のパターンのみを抽出して検討します。ライフネット生命のホームページにいくと、最初に目に飛び込んでくる項目、そして最も主張している文字列は「10秒で見積もり」という朱色のボタンです。つまり、ここからユーザーを登録に誘導したい意図が伺えます。そして「マイページ」に至るまでの遷移図を書いてみます。一部を簡略化してサラッと書くと下記のようになります。

ライフネット生命の画面遷移図

サブドメイン名から領域の境界線を読みとく

ここまでは、至ってシンプルで、プログラミングっぽいところはありません。では、画面遷移図から何を読み取るのかといえば、URLです。URLは主に「サブドメイン名」と「ホスト名」によって構成され、www.example.comであればサブドメイン名はwww、ホスト名はexample.comを指します。ここで注視すべきは、同じサービス内で、サブドメイン名またはホスト名が大きく変わる箇所があるかどうかです。これらが異なることは、システムの大きな境界線を表しており、その企業が事業領域をどのように区切っているのかのヒントを与えてくれます。

ライフネットの場合、サブドメインが鍵を握ります。一つはwww.lifenet-seimei.comであり、もう一つはsecure.lifenet-seimei.comです。通常のwwwとは別の領域として、secureという領域が準備されているわけです。つまり、2つの領域に分かれることが判明します。

2つのサブドメインの存在が浮かび上がる

では、サブドメインによって分割されている意図を推察してみようと思います。実際のフォームを入力するとわかるのですが、wwwとsecureとでは、入力項目の対象に違いがあります。それはwwwは個人を特定できる情報を扱っていない一方で、secureは住所や氏名といった個人を特定できる情報を入力するページである点です。webサービスにおいては、個人情報はセキュアな通信が必須であり、ライフネットでは思い切ってサブドメインで区切ってしまうという決定をしたことが伺えます。それほどまでに、個人情報の扱いに気を配っているわけです。

次に実際にどのようにセキュアなフォームを実現しているかを見てみます。すると、secureのサブドメインのページでは、ページ遷移やAPIを叩く際に、常に認証が求められていることがわかります。secureのサブドメインにおいて、APIで通信を行なっている箇所をGoogleChromeのdeveloper toolで解析すると、リクエストヘッダーのAuthorizationという項目に、ランダムな文字列があることがわかります。めちゃくちゃ長い文字列ですが、これが認証のtokenを意味すると思われます。このtokenを使って通信を行うことで、そのユーザーである証明に使っているわけです。また、このtokenに期限を設定することによって、一定の時間が過ぎると他人がログインできないようにし、セキュアな状態を保っていると推察できます。サブドメインにわけてまで認証を管理するという、この辺りの厳密さは「金融業」という感じがします。

めちゃくちゃ長大な文字列のtokenがある
(どんなアルゴリズムで発行されるのかを考えるのも面白い)

URIの命名規則から開発体制の価値観を読み解く

次に、各ページにおけるURL(URIとも言います→厳密な定義)の末尾を検証していきます。実は、ここがかなり面白く、興味深いところなのですが、wwwのサブドメインのページと、secureのサブドメインのページでは、末尾のURIの命名規則がまるで違うことがわかります。wwwの方は「/plan」などのわかりやすい英単語で書かれている一方で、secureの方は「app/pages/direct/a1010_010」という謎の英数字で終わる形をとっています。

a1010_010は何を示唆するのか?

一見すると単なるURIの命名の違いに過ぎませんが、これはエンジニアリングにおける価値観だったり、開発体制の違いを示唆しています。wwwの方は「わかりやすい命名」を心がける設計を重視する価値観です。一方、secureの謎の文字列が意味するものは「別の仕様書に正しい内容が定義されている」可能性が高いということです。つまり、実装者と設計者が同一である可能性が高いのがwwwであり、実装者と設計者が別人物(もしくは別会社)である可能性が高いのがsecureというわけです。

現代において、エンジニアリングの世界では、わかりやすい命名規則は何よりも重要です。その理由は、大人数で開発を高速で行い、頻繁にリリースをするという状況においては、コードやURIは、読んだ瞬間に理解できることに越したことはないからです。では、なぜライフネット生命のsecureのサブドメインでは「可読性の低いURI」を採用したのでしょうか?おそらく時代背景が大きく影響しています。予想ですが、secureのサブドメインはライフネットがサービスをローンチした2000年代後半に要件定義されたものを、今に至るまで継承しているのではないでしょうか。そして、当時においては「わかりやすい命名規則の重要性が一般に認知されづらかった」状況にあったと思われます。当時のシステム開発は、アジャイルよりは、ウォーターフォールが一般的であり、SIerによって設計され、下請けの別会社のプログラマーが実装するのが普通であり、リリース後の更新も頻繁に行うような時代ではありませんでした(あくまで推測です)。つまり、要件定義をしっかりすれば、あとはその通りにプログラマが淡々と実装すれば良い時代であり、その結果が「/app/pages/direct/a1010_020」といったURIに現れているのだと思います。空想ですが、この英数字と機能の対応表は、エクセルで管理されているのかもしれません。

これらの事情を踏まえると、ライフネット生命は、このレガシーから脱却するために、wwwのドメインではちゃんとURIの可読性を高めようとしており、エンジニアリングの方向性を是正しようと努力しているのだと思います。URIの命名規則は、一見すると些細な事柄のように見えますが、その意図や変遷を読み解けば、その組織の抱える課題や、その課題を解決するために目指している方向性が見え透いてくる気がしています。

エラー文言から業務ドメインの複雑性を読み解く

画面遷移を一通り見たら、今度はサービスの複雑性を推察しようと思います。ここで大きなヒントになるのが、フォーム入力におけるエラー表示です。

プログラミングにおいて、最も時間を使い、そして頭を悩ませるのが例外を的確に処理することです。「的確に」というのは、抜け漏れなく、全てのパターンを網羅することを意味しており、プログラミングの時間の大半をエラーハンドリングに費すことは珍しいことではありません。要件定義や仕様を決める段階において「こんな機能があったらいいよね」というのは序の口で、本当にシステムとして稼働させるためには「じゃあ、こういう例外パターンがあったときに、どう処理をするのか」を決めるのに、通常パーターンの何倍も何倍も苦労します。1つのやりたいことに対して、エラーは数倍のパターンに及ぶこともあり、実装における見積もりの精度を難しくする一つの要因です。システムの複雑性は、例外処理のパターンの数量に相関すると思います。

では、ライフネット生命では、エラーとどう向き合っているのでしょうか?今回の場合、外部に公開されているJavascriptのコードを読み解くとヒントが見えてきます。ライフネットのwebページにおいて、ビルドされたコードを地道に解析していくと、どうやらJavascript(Nuxt.js)において、あらかじめ全てのエラーの文言を記載する方法を採用していることがわかります。マニアックな話になりますが、この設計の利点は、エラー時に文言取得のための通信をその都度行う必要がなく、すでにあるJavascriptからエラー文言を参照できるため、素早くエラーを表示できる点です。UXの観点では、ストレスフリーな体験になり得ます。一方でコードデプロイ時のビルド時間が増加するため、開発体験の悪化とトレードオフの関係です。

そして、ライフネットの場合、フォーム入力時におけるエラーについて、800のパターンを超える文言を事前に準備していることがわかります。圧巻の一言に尽きます。

ビルドされたjsを読み解いていくと・・・ありました!
(出所:ライフネット公式ページの711e25a.js)

実際に数えたところ813のパターンがありそうでしたが、自信がないので800以上と書いています(違っていたらすみません)。ちなみに、keyには英数字コード、valueには日本語文言が定義されています。エラーコードの「E9」や「E8」といった部分から、どのようにエラーの境界を区切っているかを想像するのも面白いです。

実際にエラーの内容を見ると、お決まりの「お名前の漢字(名)を入力してください。」といったものから「当社からの更新手続きに関する案内について、ご連絡をする頻度はいかがでしたかに丸付き文字、括弧付き文字、ローマ数字、単位記号、旧字体の文字などは入力できません。」といった、涙なくしては読めない項目までずらりと並びます。

ちなみに、エラーが定義されたコードは、ビルドされた後のJavascriptなので、実装上のエラー文言の定義は、もっとシンプルかつ少ない量で済んでいるる可能性もあります。ただ、keyに任意のエラーコードがあるので、一つ一つ丁寧にマッピングしているのかもしれません。

ここから推察できることは、生命保険という業務ドメインの複雑性です。ライフネット生命の場合は「保険の審査」という重要な業務を行なっており、審査の材料が必要です。つまり、ユーザーは大量のフォーム入力をこなす必要があり、結果としてエラー文言の複雑さは許容しなければなりません。つまり、ドメインの複雑さが、ネット生命におけるビジネスの特色の一つであり、そのパターンを網羅することが、システム設計における鍵を握るのでしょう。そして、お客さんの入力フォームでこの様相を呈しているので、実際の保険業務、つまり料率計算や、リスク管理といったさまざまなバックオフィスの業務は、恐ろしいほどに複雑怪奇であり、全体のシステムの要件は膨大かつ複雑になっているのだと思われます。

APIから分析ツールへの投資動向を推測する

最後に、ライフネット生命のページから、外部サービスに対して叩かれているAPIを検証します。外部APIをクライアント(ブラウザなど)から直接叩くケースは、ほとんどが「分析」と「監視」であることが多く、他にはPCI-DSSの観点からクレカの秘匿情報をクライアントから自社サーバーを介さずに、直接しかるべき外部の決済会社のサーバーに送るケースがあります。これを踏まえて、ライフネット生命の外部向けのAPIを解析すると、そのほとんどが「マーケティングの分析ツール」であることがわかり、フォーム入力ページにおける分析に力点を置いていることが窺えます。

筆者は、エンジニアなので、マーケティングの解析ツールには全く詳しくないですが、叩かれているAPI(+組み込まれたjs)を見ると、有名どころの複数のツールを総動員している感があります。これらのツールは、当然有料サービスのため、ライフネット生命としては「フォームからのユーザーの離脱を避けるために、解析に十分な投資を行う」という意思決定をしていることが推察できます。

有名解析ツール。ヒントはホスト名

一方で、サービスの監視に関する外部APIは見当たりませんでした。社内向けにLogを出力しているAPIはあるものの、負荷の監視に使うNewRelicや、エラー検知のために使うSentryといった有名どころのツールは見当たらず、この辺りは投資のメリハリをつけているのかもしれません(見落としていたらすみません)。NewRelicの場合は、大規模な負荷がかかるECや決済などのサービスで利用されることが多く、ライフネットのようにユーザーの同時接続数が限られるサービスでは、費用対効果の観点から導入に見合わないという推察ができます。一方、エラーの監視については、少々、改善の余地があるかもしれません。トップページを開いたときに、debugした形跡や、外部ファイルの読み込みエラーが残っており、コードの品質を高める仕組みづくりについては、まだまだできることが多そうです。もちろん、一見するとコンバージョンに寄与しない施策「=開発者体験の向上」にリソースを投下するべきか?という議論もあります。ここも現実と理想の折り合いが難しい論点です。

筆者もdebugした形跡を、そのまま本番にデプロイした経験があります

このように、外部のAPIの通信を解析することで、どのようなツールを利用しているかがわかるため、その企業の注力領域を推察できます。答え合わせのために、ライフネット生命の決算説明会資料(FY2022/4Q)を読み解くと、成長戦略として「ウェブサイトのUI/UXの継続的改善」を謳っており、有言実行していることがよくわかります。おそらくツールを総動員して、ユーザの導線を分析し、フォーム入力の改善を行うというPDCAのサイクルを回しているのではないでしょうか。マーケティングの分析チームが強そうです。

やはり現地現物は面白い

ここまで一つのサービスを読み解いてきましたが、実際に運用中のサービスからは、推察ベースにはなるものの、いろいろなことを学べます。公開されている通信内容を1つ1つ丁寧に解析することで、そのシステムがどういった課題を抱えているのか、どのような方向性を目指しているのかも窺い知れます。そして、現実と理想の間に、どのように折り合いをつけ、どの領域に投資をするのかという考えも見え透いてきます。

さらに言えば、決算説明会で掲げた方針に対して、ちゃんと投資をしているかどうかも、チェックできるのも面白い点です。(裏を返せば、有言実行していない場合、一瞬で見抜かれます!)

「現地現物」という言葉からは、製造業がイメージされがちですが、ソフトウェアでも同じように現地現物が大切だと思っています。一見わかりづらいですが、そこにはコードという実体があり、通信を介してデータを操作しているに過ぎません。複雑ではあるものの、極めて論理的です。

ちょっと変わった万人ウケしないプログラミングの勉強法ですが、何かのヒントになれば、嬉しく思います。


yusugiura