くらしのマーケット開発ブログ

「くらしのマーケット」を運営する、みんなのマーケット株式会社のテックブログ。積極採用中です。

ログイン画面の「当たり前」を調査

みんなのマーケットでUI/UXデザイナーをしているミソサクです。

モバイルデザインの「当たり前」の変化はすごい早いです。その早さに置いていかれないように、今回は2020年9月現在の「ログイン画面」における「当たり前」を調査します。

まず、我らがくらしのマーケットのログインページはこちら。

くらしのマーケット

よくある感じですね、さて、置いていかれていないか調査に参ります。

世の中のログイン画面をみてみよう

Googleのログイン画面

Google

「メールアドレスまたは電話番号」と「パスワードを入力」する画面が別のページです。セキュリティ面の理由もありそうですが、ユーザーがログイン情報を覚えていないケースでは、この方が間違いがどちらにあるのか分かりやすそうですね。アプリでログインしようとしてもブラウザ版が起動するのも特徴です。「を入力」がパスワードの方にしか書いていないのは文字数が原因でしょうか。

Amazonのログイン画面

Amazon

「Eメールまたは携帯番号アカウントの番号」と「Amazonのパスワード」。 パスワードにわざわざ「Amazonの」と付いているのはなぜでしょう。 「アカウントの番号」なんてあるんですね、初めて知りました。

Facebookのログイン画面

Facebook

「電話番号またはメールアドレス」と「パスワード」の組み合わせです。シンプルで分かりやすく、今一番見かけるパターンな気がします。

Instagramのログイン画面

instagram

「電話番号、ユーザーネーム、メールアドレス」と「パスワード」の組み合わせです。サービスの特徴としてユーザーネームで覚えているユーザーが多そうですね。

LINEのログイン画面

LNE

「メールアドレス」と「パスワード」の組み合わせです。とってもシンプル!

Twitterのログイン画面

Twitter

「電話番号、メールアドレスまたはユーザー名」と「パスワード」の組み合わせです。Twitterもサービスの特徴としてユーザー名で覚えているユーザーが多そうですね。

Yahoo! JAPANのログイン画面

Yahoo! JAPAN

「ID/携帯電話番号/メールアドレス」と「確認コード」の組み合わせです。こちらも「ID」に当たる部分と「パスワード」に当たる部分の画面が別です。特徴としては、メールアドレスの場合でも、PCからのログインの場合でも、確認コードでログインする所です。パスワードを覚えなくていいのは便利ですね!

メルカリのログイン画面

メルカリ

まず最初に「アカウント連携」か、「メール・電話番号でログイン」かを選択します。 アカウント連携を選択するのユーザーが多いのでしょうか。「メール・電話番号でログイン」を選択後、「メールアドレスまたは電話番号」と「7文字以上の半角英数字」の組み合わせです。

UberEATSのログイン画面

UberEATS

「携帯電話番号」入力後、「OTPコードを入力してください」に4桁のコードを入力。SMSがうまくいかなかった時のために「パスワードを使用してログインする」が用意されています。こちらもブラウザ版が起動します。

TikTokのログイン画面

TikTok1

まず最初に「電話番号/メール/ユーザー名を使う」か、「アカウント連携」かを選択します。選べるアカウント連携の選択肢の数がすごいです!7つもあります! 「電話番号/メール/ユーザー名を使う」を選ぶと「ログイン」ページへ遷移し、タブで「電話」か「メールアドレス/ユーザー名」を選べます。

TikTok2

電話番号を入力すると4桁のコード入力画面に遷移しますが、こちらにも下の方に「パスワードでログイン」の導線がありました。クリックすると「パスワードを入力してください」の画面に行きます。SMSがうまくいかないケースが結構あるのでしょうか。

TikTok3

「メールアドレス/ユーザー名」のタブの中は「メールアドレスもしくはユーザー名」と「パスワード」の組み合わせでした。

TikTokは、ログインひとつに用意している選択肢の数が、圧倒的に多いですね!絶対ログインさせてあげるぞ!という気迫を感じます。

最後に

今回の調査で、「ログイン画面の当たり前」に若干遅れをとっていると感じました。「電話番号」が当たり前になりつつありますね。

「IDとパスワードは別のページ」という構成は、私の中でもっと多くのサービスの「当たり前」になっている印象でしたが、まだ「当たり前」にはなっていないのかなと感じた調査でした。

1,2年後に同じページの何がどう変化するのか、続編の調査も行いたいと思います!

AWS Summit Onlineにて、くらしのマーケットのインフラを紹介しています

昨日9/8より開催の、AWS Summit OnlineのAWS Startup Talksにて、「くらしのマーケット」のインフラ構成や、放映しているTVCMの負荷対策について、CTOの戸澤がご紹介しています。

aws.amazon.com (みんなのマーケット で、ページ内検索をお願いします)

くらしのマーケットは、2019年11月よりTVCMの放映をしています。 それまでスパイクのリクエストを処理した経験があまりなく、かつ、TVCMでどれほどの負荷が発生するかわからない状態でした。 予算を投じてTVCMを放映しても、ダウンしては意味がなく、更にユーザーにとってはネガティブな体験になります。 まずは負荷試験などできることから着手し、時間に限りもあったため、AWS含め対策を行い、放映を乗り切ることができました。 それらについて、また、業務で使用しているAWSサービスについても紹介しています。

ぜひご覧ください!

オンライン決済サービスをリリースしました

こんにちは、バックエンドエンジニアの @akira です。
今回は8月12日にリリース致しました、オンライン決済サービスの開発について振り返ってみようと思います。

今まではくらしのマーケットの支払い方法として現金のみ利用可能でしたが、オンライン決済サービスがリリースされたことでクレジットカードも選択できるようになりました。オンライン決済利用可能店舗は順次拡大しています。

くらしのマーケットにオンライン決済を導入することの難しさ

くらしのマーケットでは、以下 4 つのフェーズが主に存在します。

  1. ユーザーが予約を入れる
  2. 出店者が作業日を確定する
  3. 作業日当日、出店者がサービスを提供する
  4. 出店者がお会計をする

今回のリリースにより、ユーザー側の予約キャンセルも可能になりました。ユーザーのキャンセルはキャンセル料金が発生するケースもあり、そのキャンセル料金を出店者が回収できることが今回リリースしたオンライン決済のメリットです。

作業日当日にオプション作業を追加したり、事前に見積もっていた作業が不要になるケースもあり、予約時の金額とお会計の金額が異なるケースがあります。もし出店者がお会計の金額を誤った場合、金額の訂正を社内システムから行うこともできます。

これらの整合性を取りつつ、カード決済を導入することは非常に複雑で大変でした。

Technology Stack

今回リリースしたオンライン決済サービスの技術スタックは、以下の通りです。

  • TypeScript
  • NestJS
  • TypeORM
  • PostgreSQL
  • Domain-Driven Design
  • Clean Architecture
  • Docker
  • AWS Fargate
  • Stripe

言語は

  • 社内で長らく使ってきた言語
  • 型付き言語

の二点から TypeScript を選択しました。次点としては Golang などもありました。

また、今回初めて Domain-Driven Design(ドメイン駆動設計、DDD)を採用しました。DDD については後ほど詳しく触れます。

決済代行会社は Stripe を利用しています。

アプリケーションは AWS Fargate 上にデプロイして稼働しています。

DDD を 0 から理解する

私は昨年9月にみんマに入社したのですが、社内システムのバグを少し修正した後で今回のプロジェクトに参画しました。ちょうどその頃、オンライン決済のユーザー側開発がスタートしたばかりであり、私が最初に取りかかったタスクは、既存機能の一部を DDD を用いてアプリケーションコードのみリプレイスすることでした。

結果として、このリプレイスは失敗しました。この失敗談は、6月10日に開催しました「失敗に学べ!くらしのマーケットの開発「失敗」LT 会【オンライン/入退出自由】vol.1」にて発表しました。

minma.connpass.com

スライドは Speaker Deck にありますので、ご覧ください(趣旨:DB スキーマをリプレイスせずにアプリケーションコードのみ DDD で書き直すのは、DDD の考え方に反するものであり、アンチパターンである)。

speakerdeck.com

リプレイスに失敗後、本格的に DDD を学び直すことを決意し、Eric Evans 著書の『Domain-Driven Design: Tackling Complexity in the Heart of Software』(原著)を読破しました。このインプットにより、DDD の理解が非常に明確になりました。

ドメインの理解を深める

DDD を理解し、開発スピードが上がってきた一方で、ドメインの理解不足が顕著になってきました。DDD ではビジネスドメインの理解が必須になります。このビジネスドメインにはさらに二つ意味があると個人的に思っていて、

の双方を理解する必要がありました。

「ビジネスドメインそのもの」については、チームの PdM に詳しい仕様などを確認することができましたが、「ビジネスドメインが扱う領域のドメイン」(オンライン決済・クレジットカードの仕組み)については、きちんと理解していませんでした。

そこで書籍『カード決済業務のすべて―ペイメントサービスの仕組みとルール』を購入し、チームで回し読みすることで理解を深めました。この理解が後ほどオーソリの各種操作を実装する際に役立ちました。

DDD をチームに浸透させる

本格的に DDD でチーム開発を進めるため、チームの PdM や QA メンバーと打ち合わせを行い、認識をすり合わせました。大まかに以下の内容を共有しました。

  • ビジネスドメインの知識を常にアップデートすること
  • ビジネス用語ではなく、ユビキタス言語を使って開発者と会話すること
  • 開発者がビジネスドメインについて間違った理解を示していた場合は、必ず指摘すること

上記は基本的に普段の業務とかけ離れたものではないため、そこまで違和感もなかったのではないかと思っています。ただし、二点目のユビキタス言語を使って会話する部分は、開発を進めていくと大変だったように思います。

DDD で開発し始めた頃は、ビジネスエキスパート( PdM や QA メンバー)と開発者でそれぞれ違う単語で同じ事象を説明することが多く、それによって仕様の理解が異なってしまうことが多々ありました。後半になると、自然と認識の擦り合わせを積み重ねていたためか、ほとんど発生しなくなりました。


ここまでの技術的な詳細については、3月末に公開しました記事「DDD 開発をしてみての振り返り」に書かれていますので、合わせてご覧ください。 tech.curama.jp


主要機能を実装

ドメインモデルの数多くのリファクタリングを経て、ビジネスロジックの実装フェーズに入りました。この時は「ビジネスドメインが扱う領域のドメイン」(オンライン決済・クレジットカードの仕組み)についてはある程度知識がありましたが、一方で実装対象であるビジネスドメインそのものについては理解不足でした。

フローチャートを活用して、チームメンバー全員で処理フローを徹底的に理解したことと、仕様を理解しているかの確認を行う目的で、あまり詳しくないと実感している機能の仕様を説明し合う場を設けることで、ビジネスドメインそのものについての理解を深めました。

また、Stripe API についての理解も不足しており、ひたすらドキュメントを読んで API を実行し続けました。

Stripe API の制約を、 Clean Architecture のインフラ層とドメイン層のどちらに実装するかは難しかったですが、API を call することでチェックできるものはインフラ層、それ以外のものはドメイン層に実装しました。

ビジネスドメインの知識や Stripe の知識が揃ってきたタイミングで、主要機能の実装スピードも上がってきました。

DDD で気をつけるべきこと

無事オンライン決済サービスを DDD で実装することができたのですが、いくつか反省点がありましたのでお伝えしたいと思います。

ユビキタス言語が定まらないと、永遠にリファクタリングが続く

DDD は、ビジネスエキスパートと開発者の間で定義したユビキタス言語をそのままコードとして実装する設計手法です。そのため、開発を始める段階で、ある程度ユビキタス言語が定まっている必要があります。逆にいつまでもユビキタス言語に揺らぎがあると、それだけコードも常にリファクタリングし続けなければなりません。

よって、全てのユビキタス言語をきちんと定義した上で DDD の開発に着手するのが理想です。その状態でスタートできれば、ドメインモデルの再設計(リファクタリング)の頻度を減らすこともでき、DDD 開発のスピードアップが見込めるでしょう。

現実的には、 DDD を採用する前にユビキタス言語を整理し、将来的にどの程度変更される可能性があるかを事前に把握しておくと、ドメインモデルの設計段階で「このユビキタス言語が変更になる可能性があるので、このようにリファクタリングされるかも」などと想定することができます。

事前にビジネスドメインをよく理解しておく

DDD はユビキタス言語が変更されたタイミングで、ドメインモデルも即座にリファクタリングすることを推奨しており、初期の段階ではこれに従っていたのですが、後になればなるほどリファクタリングのコストが大きくなっていくのを痛感しました。

リファクタリングしなければいけないことに変わりはないため、できる限り初期のうちに完成形を目指してドメインモデルを設計すべきです。そのためには、ラフなドメインモデルを設計するタイミングでビジネスドメインについてある程度詳細な知識が必要でした。今回はそれが不足していたため、後半に入っても必要に応じて大胆にリファクタリングを実施してきました。

学習コスト

DDD に則った開発は、その概念(Strategic Design)から実装方法(Tactical Design)まで一定の形式に従う必要も出てきます。プログラミング言語であれば Object Oriented Programming が可能な言語、アプリケーションアーキテクチャーであれば Layered Architecture (あるいはその発展形)を採用することも推奨されています。

ある程度キャリアのあるエンジニアであれば、それらを学習してアウトプットすることは問題ないかもしれないですが、メンバーの中には比較的キャリアの浅いエンジニアもおり、その方々の学習コストをあまり考慮できていませんでした。

また、 DDD のコードをレビューできるメンバーが自チームのみ限られてしまう、といった事象も発生し、学習コストの高さを感じました。

DDD のメリット

一方、DDD を採用したことで大きなメリットもありました。

コードがとにかく綺麗

DDD と Clean Architecture が非常に相性が良く、コードが非常に分かりやすいものとなりました。

ドメインモデルをリファクタリングする際も、基本的にドメイン層だけ変更すれば良いですし、バグが見つかった場合の修正も比較的容易でした。

ビジネスドメインをきちんと理解した上で開発できる

これはむしろ DDD の恩恵そのものと言えますが、ユビキタス言語をそのままコードとして実装するため、ビジネスドメインを理解した上で開発することができます。

特に今回は、前述の「ビジネスドメインが扱う領域のドメイン」(オンライン決済・クレジットカードの仕組み)まで理解した上でコードをかけたのが一番良かったです。

DDD はクックブックではない

最後に、DDD の開発を一通り経験して個人的に主張しておきたいことがあります。それは「DDD はクックブックではない」ということです。

DDD の価値はその開発プロセス自体にあり、上部だけを擬えてもあまり効果は出ないと私は思います。

『Domain-Driven Design: Tackling Complexity in the Heart of Software』が出版されたのは 2003 年ですから、DDD を採用し始めた頃は「これってちょっとレガシーな設計手法なのでは」と正直思ってしまったこともありました。

しかし、DDD は概念の一種であるため、いつまでも応用ができます。特に Strategic Design の部分は、どれだけ技術が移り変わっていっても不変ではないでしょうか。

一方で、 Tactical Design の部分は時代とともにアップデートされていくでしょう。その一例として、昨今流行の Microservice Architecture があります。

よく「一マイクロサービスは、一つの境界づけられたコンテキストに相当する」といった考え方を見受けますが、Eric Evans 氏はこの考え方に警鐘を鳴らしています。

prescriptive guidance such as "each microservice is a bounded context" approaches the "cookbook" end of the spectrum, and diverges from the sweet spot of DDD.

「こうすればできる」といった方法論はクックブックに過ぎず、そのやり方では DDD の真価を発揮することはできないでしょう。そのため、本格的に DDD で開発をするのであれば、DDD を根本から理解することから始めるべきだと私は思います。

BashとPSQLを使う時の注意事項

こんにちは!エンジニアのカーキです。 今日はBashPSQLを使ってSQLを実行した時にハマったエピソードについて紹介したいと思います。

なにでハマったのか?

自分が書いたBashスクリプトpsqlを使っていくつかの簡単なSQL (主にINSERT, UPDATE, DELETE)を実行しようとした時にスクリプトが成功してもデータベースには期待していた変更がありませんでした。

実行していたSQLは今まで成功していたSQLだったので正しいと思い込んでスクリプトの動作だけで確認してたのですが、実はpermission 関係でSQLが失敗していたようです。ただ、Bashスクリプトのエラー時の設定とpsqlの実行方法によってSQL上のエラーに気付かず、スクリプトが最後まで走って、成功したように見えたいただけでした。

エラーに気付かなかった要因とその解決方法

要因 1.

Bashはデフォルトで実行途中でエラーになっても次に進むので注意しなければならない。

例: 以下のスクリプトを実行すると、cd のところでエラーになりますが、スクリプトはそこで中断されず、次の echo コマンドまで実行されてしまう。

#!/bin/bash

echo "This should run"
cd 存在しないパス
echo "This should not run!"

実行結果:

~/workspace ❯ ./hoge.sh
This should run
./hoge.sh: line 4: cd: 存在しないパス: No such file or directory
This should not run!

~/workspace ❯ 

解決方法:

-e フラグをセットすることで、エラーになったらすぐにスクリプトが止まるようにすることができます 。-e をセットするとBashが各コマンドの終了ステータス (Exit status)を確認し、0(成功)以外の終了ステータスが出たらスクリプトを止めてくれるみたいです。

-eフラグは以下のいずれかのやり方でできます:

  • シバンに -e を付ける
    #!/bin/bash -e

    echo "This should run"
    cd 存在しないパス
    echo "This should not run!"
    #!/bin/bash

    set -e
    echo "This should run"
    cd 存在しないパス
    echo "This should not run!"

実行結果:

~/workspace ❯ ./hoge.sh
This should run
./hoge.sh: line 4: cd: 存在しないパス: No such file or directory

~/workspace ❯ 

要因 2.

Postgresを使っていればpsql (Postgresのクライアント) を使ってSQLを実行することがよくありますが、その時に注意しないとエラーに気付かない場合があります。

psqlSQLコマンドを実行したい時に、ファイルから実行する方法と直接 psqlコマンドに-cオプションで実行する方法がありますが、それぞれ少し挙動が違います。 -cで実行した場合SQLでエラーになったらpsqlコマンドの終了コードが1 (エラー) になりますが、ファイルを流してSQL実行した時に終了ステータスが 0になります。

ということは、もしBash-cSQL実行してエラーになったらBash的にエラー扱いになりますが、同じSQLをファイルで流して実行すると終了ステータスが0になるので成功扱いになってしまいます。

例: 必ずエラーになるSQLを両パターンで実行してみましょう。 エラーになるように存在しないテーブルをSELECTしてみます。

  • -cオプションで実行した場合:
    ~/workspace ❯ psql -U postgres -h localhost -p 5432 postgres -c "SELECT * FROM foo"    
    ERROR:  relation "foo" does not exist
    LINE 1: SELECT * FROM foo
                        ^

    ~/workspace ❯ echo $?
    1    
    👆 終了ステータス !=0 なのでエラー扱いになる
  • ファイルに同じSQLを書いて実行した場合:
    ~/workspace ❯ psql -U postgres -h localhost -p 5432 postgres < foo.sql
    ERROR:  relation "foo" does not exist
    LINE 1: SELECT * FROM foo
                        ^

    ~/workspace ❯ echo $?
    0
    👆 終了ステータス = 0 なので成功扱いになる

例の通り、psqlでファイルを流してSQL実行した時にSQLでエラーが出ても終了コードが0になるので、エラーになった時に気付きづらいです。こうなるといくらBash-e フラグをセットしてもエラーとして扱われないので危険です。

解決方法:

psql コマンドに ON_ERROR_STOPオプションをセットすれば、エラーになったらすぐにスクリプトが中断されるようになります。

例:

~/workspace ❯ psql -v ON_ERROR_STOP=1 -U postgres -h localhost -p 5432 postgres < foo.sql
ERROR:  relation "foo" does not exist
LINE 1: SELECT * FROM foo
                      ^

~/workspace ❯ echo $?
3
👆 終了ステータス != 0 なのでエラー扱いになる

以上Bashpsqlを使った時の注意事項でした。終了ステータスをちゃんと意識しないとハマりやすいところだと思うのでみなさんも気をつけましょう!

GitHub Actions もしものときの timeout

みんなのマーケットの バックエンド/SRE を担当している、マノメです。

今回は、GitHub Actions で起こった障害に巻き込まれて失敗に気づいた、という例をご紹介したいと思います。

なお本記事は、6/10 に開催した 「失敗に学べ!くらしのマーケットの開発「失敗」LT 会 vol.1」 での LT 内容を再構成したものです。

f:id:curama-tech:20200821162334p:plain

GitHub Actions の活用

この記事を読んでいる方は既にご存知かもしれないですが、GitHub Actions は、以下のような特徴がある超便利な CI/CD ツールです。

  • GitHub 謹製の CI / CD ツール
  • 基本無料 (月ごとの時間制限あり、それ以降は課金)
  • 実行環境は Linux / Win / Mac を選べる
  • 様々な言語が動かせる (Docker イメージもいける)
  • OS や言語のバージョンをマルチビルドできる
  • シークレットキーの設定も簡単
  • docker-compose が使える (最近知った)
  • yaml でタスクを書くだけで作れる

ほかにも特色はいろいろありますが…。

f:id:curama-tech:20200821162420p:plain

弊社では、この GitHub Actions をプロダクトの一部でほんのり活用しています。
テストなどがコケている場合、master ブランチにマージできないようになっており、コードの品質をある程度保てるようにしています。

突然、Actions が終わらなくなる

ある日、突然 GitHub Actions のタスクが終了しなくなりました。

f:id:curama-tech:20200821162431p:plain

これによって、困ることがあります。

  • 追加でお金がかかるようになるかもしれない!
    • Actions は、一定の時間以上は課金制になってしまう
  • Pull Requests がマージできない

結局調べた結果、Nodejs のダウンロードが起因する障害でした。
(この時起きていたことの詳細はこちら: actions/setup-node/issues/132)

要するに、Nodejs の ダウンロードができなくなり(503)、Actions の「Use Node.js 12.x」が止まっていました。 これによって、タスクがリトライを繰り返し、なかなかエラー終了しない状態になっていました。

timeout を設定しよう

もしも Actions に何かあった時のために、タイムアウトする設定を入れると安心できます。
Actions 全体でかかった時間が計測されているので、その時間にリミットをかけられる機能です。

Actions はタスクを yaml で表現します。
この中で、build のオプションとして timeout-minutes を設定するだけでタイムアウト値を設定できます。

f:id:curama-tech:20200821162510p:plain

しかし、私はここでさらに失敗しました。

タスクにかかる時間が 1 分弱であるのに対してタイムアウト値を 1 分に設定していましたが、 コードの量や Actions 内のネットワーク環境の影響などでタスクの時間が 1 分を超えることがある、というのを考慮できていませんでした。
そのため、全然 Actions が Success にならなくなっていました。

Actions のタスクの実行時間は、状況に応じて変わります。
実行時間は適切なバッファをもたせつつ、適切な時間を設定するようにしましょう。

まとめ

今回は Github Actions をクリティカルなものに使っていなかったため、影響がほぼなかったのが幸いでした。
こういう細かい設定をちゃんと設定して、もしものときに備えておきましょう。
そして、どんどん GitHub Actions を活用していきましょう!