トレタ開発者ブログ

飲食店向け予約/顧客台帳サービス「トレタ」、モバイルオーダー「トレタO/X」などを運営するトレタの開発メンバーによるブログです。

マイクロサービスへの挑戦とその結果

こんにちは。エンジニアのkitagawaです。

こちらはトレタアドベントカレンダー2021 21日目の記事です。

今年は新規サービスのトレタO/Xに心血注いだ一年でした。 振り返りを込めて、トレタO/Xのバックエンドとしてマイクロサービスを導入したことについて紹介します。

新規サービス「トレタO/X」

www.toreta-ox.com トレタO/Xは飲食店向けのモバイルオーダーアプリです。飲食店の来店者はテーブルごとに渡されるQRコードが印字された紙を自身のスマートフォンで読み込んで、トレタO/Xアプリを開きます。 トレタO/Xから料理の注文が行えて、オンライン決済でスムーズに退店することができます。

トレタO/Xの特徴としては、そのお店ごとの雰囲気を表現したリッチなUIです。 そのためシステム構成は、メニューブックを柔軟に表現できるように各社ごとにフロントエンドのアプリをそれぞれ作っています。 一方でバックエンドは共通の機能を提供するSaaSモデルを提供しています。 そうすることで、各社ごとに異なったUIを提供しつつ、共通のバックエンドで機能エンハンスを行えるようにしています。

f:id:mkitagawa-312:20210803101055p:plain f:id:mkitagawa-312:20210803101115p:plain

マイクロサービスを導入した背景

トレタO/Xの開発が本格的に始動したのは約2年前です。 コロナ渦で飲食店が厳しい状況を強いられている中、トレタも大きな打撃を受けました。 そこで今まで予約台帳サービスをはじめとする飲食店の「予約」事業の会社から、「飲食店支援」の会社へ変わろうと新しい事業の模索が行われました。 いくつかの新規サービスが立ち上がり、その中で注力事業として置いたのがトレタO/Xです。

トレタO/XはプロトタイプでのPoC期間を経て、次はシステムをスケールさせるために製品版としてバックエンドのリニューアルを行いました。 その際にシステム構成を検討する上で主軸とした考えが、システムの再利用性です。

「強くてニューゲーム」ができる開発組織

トレタO/Xを予約事業の次の事業の柱にする意気込みでバックエンドの設計検討を行いましたが、 その先を見据えるとトレタが次は単に「オーダーアプリ」の会社になるのではなく、「飲食店支援」の会社として今後も次々と新規サービスを出していく会社になる必要があると考えました。

そこでトレタO/Xのシステムはその足がかりとなるように、トレタO/Xで作ったシステムの一部が他の新規サービスでも再利用できるような構成を理想の姿としました。 そうすることで、今後の新規サービスを立ち上げる際には毎回0からのスクラッチではなく、資産を流用することで開発期間が短縮された「強くてニューゲーム」が行える組織になると考えました。

そのため、「O/Xのバックエンド」ではなく「トレタの共通基盤システム」として、特定のコンテキストで区切られたシステムを組み合わせて構成するマイクロサービスを自然と選ぶことになりました。

トレタO/Xのシステム構成

f:id:mkitagawa-312:20211220230607p:plain トレタO/Xのシステムは大まかに以下のマイクロサービスで構成されています。

  • 認証サービス
    • Auth0をベースにし、各種サービスごとの権限やロールなどを管理するサービス
  • 注文サービス
    • トレタO/Xのメインとなる注文データやユーザーのセッション情報を扱うサービス
    • 変更履歴が全て保存されるDatomicをDBとして、Clojureで書かれたGraphQLサーバー
  • 決済サービス
    • 決済や返金なでの決済処理や決済データを管理するサービス
    • Stripeなどの決済プラットフォームをラップし抽象化する
  • 印刷サービス
    • 注文データやQRコードをキッチンプリンタへ印刷するサービス
    • 印刷ジョブを管理し、ネットワークプリンタから定期的に送られてくる印刷ジョブチェックのリクエストを捌く
  • APIサーバー
    • クライアントアプリと各種マイクロサービスとの間をかけもつファサード層
    • 外部公開用のAPIを提供する

ご覧の通り使用している言語がバラバラでも成立するのがマイクロサービスの一つの利点かと思います。 技術選定は在籍エンジニアの技術スタックであったり、システム要件としてデータベースにあわせた言語や連携先サービスのSDKの提供状況などを加味しています。

マイクロサービスにしてみて

「マイクロサービスは銀の弾丸ではない」とはよく言われるもので覚悟はしていましたが、やはりいろいろと地雷は踏みました。

分散トランザクションによる問題

  • タイムアウトなどにで一部にだけデータが入りロールバックできず不整合
  • リトライや冪等性、到達保証など考慮する点が多い
  • トラッキングIDを入れないと調査に一苦労
  • 結局は分散トランザクションが生じている時点でドメイン境界が正しく切れていない

インフラコストの問題

  • それぞれのコンテナ実行環境構築と管理するためのインフラエンジニアが不足
  • デプロイさせるシステムの順番を間違えると事故が起きる可能性もある

徐々にマイクロサービス化するという幻想

苦労する部分は多いですがやってみて良かったと思うことの一つに、最初からマイクロサービスを前提にしていたからこそ正しく正規化や抽象化されたデータ構造に近づけたという点です。

「初期の段階からマイクロサービスにするな」というのもよく言われる話です。 ただ、モノリスをつくってから徐々に切り出していく、というのもそう簡単ではありまえせん。 トレタでも予約台帳のサーバーは約8年越しの巨大なモノリスとなっており、部分的に切り崩そうとしてもデータが依存しあったりコードが絡みあっていたりで、話があがるたびには消えていました。 そもそもリプレイスや大規模リファクタリングは事業フェーズのタイミングとリソース(人、金)が揃わないとなかなか行うことができません。

今回のようにPoCでコンテキストの境界を検証したり仕様を概ね出し切っておき、プロトタイプを脱する時点でマイクロサービスを検討するのは良いタイミングだったかと思います。

さいごに

マイクロサービスにするとやはりエンジニアの頭数がどうしても必要になってきます。 トレタではエンジニアの採用を現在全方面オープンしています。 飲食店のDX化が急速に進んでいる昨今で、一緒に未来の飲食業界を作っていく仲間をお待ちしてます!

www.wantedly.com

アクセシビリティ本の輪読会をした話

こんにちは。フロントエンドエンジニアの白濱です。

この記事は トレタ Advent Calendar 2021 の 19日目の記事です。

昨年のアドベントカレンダーでは 「アクセシビリティを気にし出したきっかけと、2020年の振り返り」 という記事を書きました。

zenn.dev

その中で、「来年は輪読会をやるぞ!」と言っていました。

今年実際にアクセシビリティ本の輪読会を行なったので、この記事ではそのことについて振り返りたいと思います。

プロダクト開発部の有志での輪読会を提案

去年のアドベントカレンダーを書いている最中、気持ちが高まって勢いで提案しました。

当時は仕事で関わりがあったデザイナーさんがお一人だけだったということもあり、提案した時ちょっとドキドキしていた気がします。笑

f:id:punipunityan:20211216032459p:plain
f:id:punipunityan:20211219001919p:plain

輪読会開催の目的

輪読会を提案した目的は以下のようなものでした。

  • アクセシビリティに関して知り、考えるきっかけを作ること
  • アクセシビリティ向上に取り組む土台を作ること
  • プロジェクトを超えてデザイナーとエンドエンジニアの情報共有を気軽に行えるようにすること

2021年上期の輪読会

読んだ本

www.amazon.co.jp

まずは、「デザイニングWebアクセシビリティ - アクセシブルな設計やコンテンツ制作のアプローチ」 を読みました。

わかりやすい具体例が多く掲載されており、初心者にとってとても読みやすい本です。

この本を選んだ理由は、有識者の方からおすすめされた本の中で、一番デザイナーと一緒に読みたいと思っていた本だからです。

去年、実装面での改善を行おうとした際、実装だけでは変えようがないことが思っていたより多いと感じました。

そのため、デザイン時点でアクセシビリティの考慮が必要なことを一緒に学びたいと思っていました。

輪読会の進め方

参加メンバーはデザイナー全員に加え、興味を持っていたエンジニア・PMで合わせて5〜10名ほどで行なっていました。

進め方はメンバーで相談し、以下のように進めていました。

  • 毎週月曜日17時から18時開催
  • 事前準備なし
  • 前半30分、各自黙読(毎回約20ページほど)
  • 後半30分、感想・疑問など自由に共有
  • 議事録をとって共有

各々属しているプロジェクトで多忙だったため、なるべく負担にならないやり方を採用しました。

1冊読み終わったあとは、読んで終わりだと勿体無いので、それをどう業務に活かしていくかを考えました。

結果、実際に取り組んでいきたいと思う箇所をまとめてチェックリストを作成することにしました。

f:id:punipunityan:20211216034603p:plain

チェックリストを独自で作った理由は

  • 自分たちで本を見返してピックアップすることにより、気をつけようという意識が高まること
  • まずは小さく始めるため、いくつかピックアップする方が良い

と考えたからです。ただ、まとめみると結果的に80項目ほどになり、いきなり始めるにはちょっと大変な量になりました。

チェックリストを作って以降、運用は個人任せにになっているので、今後のやり方は考えていきたいです。

2021年下期の輪読会

1冊読み終わった時点で、当初の目的としていた

  • アクセシビリティに関して知り、考えるきっかけを作ること
  • プロジェクトを超えてデザイナーとエンドエンジニアの情報共有を気軽に行えるようにすること

は達成できたと感じていました。

その上で、より学んでいきたいと言う声が多かったので下期も輪読会を行いました。

読んだ本

www.amazon.co.jp

下期は「Form Design Patterns ―シンプルでインクルーシブなフォーム制作実践ガイド」という本を読みました。

こちらの本も具体例が多く掲載されており、今後も読み返したい一冊です。

トレタの既存プロダクトを時折振り返りながら読み進め、有意義な輪読会となりました。

輪読会の進め方

下期も上期とほぼ同じような進め方でしたが、議事録のとり方は変えました。
上期は私が議事録を書いていたのですが、下期は各自読みながら感想や疑問点をまとめる形に変更しました。
このやり方に変更することで、それまでより効率的に進めることができるようになりました。

輪読会を終えて

最後に、輪読会参加メンバーから輪読会の振り返りコメントをいただいたので紹介したいと思います。 (わかりやすくするため、デザイナーとエンジニア分けて掲載しています。)

良かったこと

デザイナー

  • 輪読会という形式でエンジニアと一緒に読み進めたので、ディスカッションすることで理解度が増した。
  • フォームのUI・作法の理解度が深まったことで、デザインとして採用する際にもなぜこれが適切なのか説明しやすくなった。アクセシビリティを理解せずに推奨されたフォームをアレンジすると機能しなくなるケースもあるなど学びも多かった。
  • トレタのプロダクトにもあるようなフォームが実例をもとにまとめられており、既存のUIにもアクセシビリティ観点で問題のある箇所を発見することができた。例えば、これまではスクリーンリーダーユーザーに対して読み上げられる要素や順番について考慮ができていなかったことなど。

エンジニア

  • これまで意識できていなかったことも多々あり、認識を改めることができた
  • 本で読んだことに関して共通認識が持てているので、実際の業務における相談がやりやすくなった
  • 普段業務で関わっていないデザイナーともコミュニケーションを取りやすくなった

課題に感じたこと

デザイナー

  • これまでトレタは飲食店向けのtoBプロダクトが主要でユーザーの状況もある程度限られており、「誰にとっても使いやすいこと」より「特定のユーザーにとって使いやすいこと」を重視したいた。でもO/Xのようなプロダクトではこれまでのスタンスを見直す必要がある。知識の習得で終わらせずに、既存プロダクトの改修など実践に移すためにどう取り組むかが今後の課題。

エンジニア

  • チェックリストを作ったが、運用が個人任せになっており取り組みにくい状態になっている
  • 自動チェックの仕組みを増やすなどやりたいことはたくさんあるが、なかなか時間を作れていない
  • アクセシビリティ輪読会から実践に移していく場合、輪読会として動き続けるのは難しい。サブプロジェクトもしくはプロジェクトとして立ち上げたりと、やり方を考える必要がありそう。プロジェクト毎の改善活動の一貫としてやるのが現実的かも。

今後取り組んでいきたいこと

デザイナー

  • フォーム周りは文字入力の時など実際触ってみないと気がつかないことが特に多い。デザイン段階でもユーザーの状況・環境を具体的にイメージできるようプロトタイピングなどで積極的に検証していきたい。
  • 既存プロダクトのアクセシビリティチェックをして現状の問題点を把握したい。そのうえでトレタのサービスに触れるユーザーの特性を整理して、まずは最低限遵守するべきアクセシビリティのルールを作りたい。
  • 策定したルールをもとに既存コンポーネントの再整備を行いたい。

エンジニア

  • まずは、自身が関わっているプロジェクトで「知覚可能」のチェックを行い、issueを作成を行いたい
  • 自動チェックの仕組みを増やしたい
  • 改善のための時間を確保したい

おまけ:フロントエンドチームへの知見共有

この記事では輪読会にフォーカスして振り返りましたが、そのほかの取り組みも少し紹介させてください。

フロントエンドチームでは週一で定例があり、そこで技術共有会を行なっています。 自分のターンの時は、主にアクセシビリティ関連の情報共有を行いました。

以下、話題にした内容です。

  • 個人的に、「東京都新型コロナウイルス感染症対策サイト」のアクセシビリティプレ試験に参加したので、その際のTips共有(どんなツールを使ってどういったチェックをした、など)
  • アクセシビリティ輪読会で作成したチェックリストに関する共有
  • 自動チェックツールをいくつか検討している話(stylelint-a11y、acot)
  • カルーセルUIが嫌われている理由を改めて考えた話(とても盛り上がった)
  • 「知覚可能」の観点で自身が関わっているプロジェクトの改善点を検討した話
  • 押せないボタンがデフォルト非活性なのは推奨じゃないらしいという話(これも盛り上がったと思ってる)

(ここでは詳しいことはここでは書きませんが、雰囲気だけ伝わればと思います。)

終わりに

2021年アクセシビリティ改善に費やした時間は、自身の稼働でいうとの2%に満たないと思います。
関わっているプロジェクトの 0->1フェーズであったこともあり、アクセシビリティ改善活動に割く余力が正直あまりありませんでした。

それでも、確実に成果があった1年だと思っています。

昨年、アクセシビリティ啓蒙活動をされている方から、

「勝手にPRを出すのはアンチパターン」

というお話を聞いてから、ひとりで進めてしまわないよう輪読会の実施や、フロントエンドチームへの知見共有を心がけてやってきました。(どちらにせよ、ひとりでできることは限られますが。)

今年、それはできたと思っています。

来年は、実際の改善をより進めていけるよう、取り組んでいきたいと考えています。

トレタでは一緒に働くメンバーを募集しています!

トレタは、エンジニアとして色々とチャレンジできるチャンスが多い環境だと思っています。

少しでも興味があれば、カジュアル面談などお気軽にご応募ください!

www.wantedly.com

corp.toreta.in

Flutterアプリにテストコードを書きました。

はじめに

この記事はトレタ Advent Calendar 2021の15日目の記事です。

こんにちは、iOSエンジニアのarisaです。
本日は、Flutterのテストを書いたはなしです。

弊社のトレタO/Xでは、大きく分けて2つのプロダクトがあります。
お店のスタッフさんが使う画面と、お店に来たお客さんが使う画面です。
そのうち、お店のスタッフさんが使う方のアプリでは、Flutterを採用しています。
今回私がテストを実装したのは、そんなお店のスタッフさん用のtoBアプリです。

やったこと

とても簡単なユニットテストから実装し始めました。 Intから「〇〇円」というString表示に変換するextensionを例とします。

extension OxInt on int {
  String formatYen() {
    final numberFormat = NumberFormat('#,###');
    return '${numberFormat.format(this)}円';
  }
void main() {
  group('formatYen', () {
    test('basic', () {
      const price = 1000;
      final result = price.formatYen();
      expect(result, '1,000円');
    });

    test('zero', () {
      const price = 0;
      final result = price.formatYen();
      expect(result, '0円');
    });

    test('cheap', () {
      const price = 100;
      final result = price.formatYen();
      expect(result, '100円');
    });

    test('Expensive', () {
      const price = 1000000;
      final result = price.formatYen();
      expect(result, '1,000,000円');
    });

    test('minus-cheap', () {
      const price = -100;
      final result = price.formatYen();
      expect(result, '-100円');
    });

    test('minus', () {
      const price = -1000;
      final result = price.formatYen();
      expect(result, '-1,000円');
    });

    test('minus-expensive', () {
      const price = -1000000;
      final result = price.formatYen();
      expect(result, '-1,000,000円');
    });
  });
}

こんな感じで少しずつ実装しています。
実は今まで、私はテストコードに触れたことがなかったため、たった1つの関数でもこれだけ複数の状況について考慮しなければいけないとは……と少し驚いてしまいました。
私はO/Xの開発チームには遅れて加わったのですが、テストコードを書くためには元のコードをしっかり理解しないといけないので、
今回の実装により、だいぶん理解が深まって来たのではないかと思っています。

私がテストコードを担当するまで、テストのカバー率は約7%でした。
でも、この1ヶ月で約2倍の13%まで上昇させることができました。
引き続き来年もテストのカバー率を上げていき、安定した開発の一助となれればと思っています。

最後に

トレタでは一緒に開発する仲間を募集しています。
興味がある方は是非カジュアル面談へお越しください!

www.wantedly.com

© Toreta, Inc.

Powered by Hatena Blog