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

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

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 を活用していきましょう!

くらしのマーケットの開発チーム紹介!

みんなのマーケットでPdMをしているハットリです。

今回はくらしのマーケットを開発しているテクノロジー本部のチームを紹介していきたいと思います。

テクノロジー本部では

機能をより使いやすく

より、「探しやすく」「予約しやすく」「払いやすい」ものにしていくために、新規カテゴリの追加、既存カテゴリの機能改善を進めます。

「オススメできる」カテゴリをより多く

本当に友人にオススメできるカテゴリをよりたくさん増やしていくために、新規カテゴリの追加、既存カテゴリの既存改善を進めます。

をミッションにくらしのマーケットの新規機能開発や運用保守を行っています。


f:id:curama-tech:20200814161637j:plain

チーム紹介

🚀 カテゴリチーム

くらしのマーケットの各カテゴリの売上を成長させるために、市場調査からプロダクトの企画・改善案の発案、運用の改善、また、そのKPI管理まで一気通貫して行うチームです。

車内清掃サービスや土嚢積み(浸水対策)といったカテゴリの新設や社会情勢に合わせた特集・キャンペーンの企画も行っています。

チームメンバーからの一言
売上の成長をミッションに担うため、他部署をも巻き込んでいく必要があり、高い調整力が求められます。 そういうシビアな面もありますが、メンバーそれぞれ異なる得意分野を活かして、お互いにアドバイスしたり助け合っていける空気感のチームです



💳 決済・認証チーム

くらしのマーケットの決済に関する開発を行うチームです。

通常のECサイトでの支払いはオンライン決済が最も一般的ですが、出張訪問サービスの業界ではまだまだ現金というアナログな決済手段がメジャーになっています。
この業界を仕切るプラットフォーマーとして、利用者(出店者・ユーザー)の体験向上のために、業界を変えていく責任があります。

キャッシュレス導入を進め、お金の流れをスムーズに、そして透明にしていきます。

チームメンバーからの一言
少数精鋭のチームなので、役割に留まらず責任を持ってコミットできる方を求めてます!



🛠️ リフォームチーム

くらしのマーケットのリフォームカテゴリの利便性の拡充を行うチームです。

巨大な住宅リフォーム市場には、商品を含めた作業料金の総額が不明瞭である点や、小規模な作業においても見積もりに多くの工数が発生する点など、多くの課題が存在しています。

トイレリフォームや給湯器交換といったカテゴリを「商品+工事費込の値段」で比較検討でき、煩雑な見積もりをすることなく、作業料金を事前に把握できます。

チームメンバーからの一言
見積もりなんかいらない!リフォームもパッケージ化の時代だ!今までになかったそんなサービスを一緒に作りましょう!



🤝 マッチングチーム

くらしのマーケットの現在の仕組みでは解決できていない課題を解決するチームです。

「料金がわかりやすい」「人とサービスで選べる」というバリューを担保しつつ、会員登録から作業までの流れを簡略化することでニーズを満たします。

チームメンバーからの一言
新しい仕組みを一から作っています!ローンチ後のユーザーの反応が待ち遠しいです!



🚅 即応チーム

くらしのマーケットの特定のプロジェクトを持たず、他のチームが自分たちのやるべき開発に集中できる環境を作り、足りない役割を補うチームです。

具体的には依頼タスク(バグ修正、繁忙期対策、CM連動企画)、他部署からの開発要望、他チームの開発ヘルプをしています。

チームメンバーからの一言
33%が新卒、40%が海外の方です。新メンバーはまずこのチームに入隊し、広くいろいろな部署との開発に関わることでくらしのマーケットの仕組みを理解します。各国の先輩がいるので日本語のケアもできます!



🔍 QAチーム

くらしのマーケットの全ての機能に不具合がないこと、サービス利用者が「〇〇にくい」ではなく「〇〇やすい」状態であることを検証するチームです。

サービス利用者が何かを気にせず使える状態になっていることは、プロダクト本来の目的が達成されるために必要な前提条件であり、この条件を満たした上で、3つの観点(製品・データ・利用/操作)で品質保証に尽力しています。

詳しいお仕事紹介記事はこちら

チームメンバーからの一言
昼はQA、夜はやきとり屋!元ヤンのマリと、昼はQA、夜は家事代行、元パティシエのザキで頑張っています。開発エンジニアより圧倒的に人数が少ないのでメンバー絶賛募集中です!



最後に

6チームに分かれて開発を行っていますが、ミッションを達成するという同じ気持ちを持って開発を進めています。

テックチームでは「くらしのマーケット」を一緒に作る仲間を募集しています。

ぜひコーポレートサイト までお気軽にご連絡ください!