Diverse developer blog

株式会社Diverse(ダイバース) 開発者ブログです。

FlutterKaigi 2024に参加してきました

はじめに

昨年に引き続き、今年もFlutterのカンファレンス、FlutterKaigi2024に参加してきました。

今年は11月21日と22日の2日間にわたり開催され、例年以上に多くのセッションに参加することができました。

会場は有明セントラルタワーホール&カンファレンスで、セッションは2つのホールで行われました。スポンサーブースも2箇所に設置され、会場は非常に賑やかでした。

今年もFlutter製でFlutterkaigiのアプリが作成されており、リポジトリが公開されているのでこちらからも多くの学びが得られそうです。

github.com

どのセッションも非常に学びが多く素晴らしいものでしたが、中でも特に印象深かったセッションについての感想を綴ろうと思います。

印象に残ったセッション

出前館アプリにおけるFlutterアプリ設計とそれを支えるCICD環境の進化

元々React Nativeで作成されていた出前館のクライアントアプリをflutter化するにあたり、どういったフォルダ構成やアセット管理また状態管理をどのように行うかの発表がなされていました。

まずフォルダ構成として

  • Type/Domain
  • Feature
  • Package

この三つが候補としてあげられており、プロジェクトの規模等を考えてFeature型を採用されたようでした。弊社も元々はType/Domain型で運用しておりましたが、プロジェクトの規模が大きくなるにつれファイルを検索しずらい等の問題が発生したためFeature型に移行した経緯があります。

アセット管理にはflutter_genを使っているとのことでした。BuildContextをextensionしてcontext経由でアセットへアクセスしているという工夫もお話しされていました。弊社でもflutter_genを採用しており、flutter_genが自動生成するSvgGenImage, AssetGenImageをextensionしてなるべく不要な引数やデフォルト引数を設定することでアセットへのアクセスを簡易にする工夫をしています。アセット管理に関するベストプラクティスについて、本発表を機会に今後もっと追求していければと思いました。

状態管理にはBLoCを状態を示すStateにはFreezedを採用されているとのことでした。BLoCについては未経験だったためどういった使い方をするのかを知れてよかったです。Freezedは弊社でも採用しており利便性の高さは共感するところでありました。

最後にCI/CD環境についてお話しされていました。当初はBitriseを採用するところから始まったというお話しからはじまり、BtoBアプリのflutter化に追従する形でTeamCityへ移行されていったというお話しをされていました。複数チームが存在する中で、オンプレ環境でバージョンの異なるビルド環境でCI/CDをしていくことで発生する苦労があることを知れました。

発表概要

2024.flutterkaigi.jp

発表資料

speakerdeck.com


気をつけたい!Desktop対応で陥りやすい罠とその対策

本セッションではDesktop対応をするにあたり事前に知っておかなければ陥ってしまう特有の罠とその対策についてお話しされていました。Desktop対応とありますが、Webも含む広義の意味で使用されています。なのでPadやブラウザ等のマルチデバイスでのレスポンシブ対応における内容も含まれていました。

まず文字入力時の文字数制限がアプリでは問題なかったものがWebだと入力言語を切り替えた際に制限できなくなる現象についてお話しされていました。こちらはTextFieldのmaxLengthEnforcementにenforcedを指定することで解決できるようでした。知らなければ絶対に陥ってしまう罠なので本発表でTipsを知れてよかったです。

次にスクロール可能なWidgetがWeb対応することによってできなくなる現象についてお話しされていました。こちらはマウスによるドラッグを有効にするプロパティを明示的に指定することで解決されたとのことです。アプリ版のみであればタッチによるドラッグしか考えなくてよいですが、デスクトップ等の対応をする場合はマウスによるドラッグも念頭においておく必要があることが知れました。

次に画面レイアウトに関わるレスポンシブ対応についてお話しされていました。 BottomNavigationBarをWebで利用するとタブ間のすき間が大きくなり使いづらくなってしまうため、左側にメニュー一覧を表示することができるNavigationRailを採用されたとのことでした。Material3のWindow size classesを基準にBottomNavigationBarとNavigationRailを切り分けていました。

またNavigationRailの最下部にメニューを表示したいというデザイナーさんからの要望を実現するためにtrailingプロパティを利用して実現しようとしたが、想定していたものと全く違う表示になってしまい、それでも実現するために試行錯誤した結果コードがとても複雑化してしまったようです。 そこでデザイナーさんに相談した上でデザインを調整してもらい解決できたようです。この事例のようにflutter側では解決できないこと・解決しようとするととても複雑になってしまいメンテナンス性が損なわれてしまう場合には相談してデザインを変えることで解決するということは実際の現場では大切なことであると感じました。

最後にWeb特有の課題についてお話しされていました。アプリほどには成熟していないDesktop領域では実装してみると様々な課題にぶちあたることになり、その際にどういった行動をとればいいのかが明確になりました。

  • flutterのissueを検索する
  • Widgetのプロパティを詳しくみてみる
  • 公式のドキュメント、MigrationGuideをちゃんと読む

とても基本的だとされていることですが、ちゃんとできてないことも多いので、本発表を期に改めて意識したいことだと思いました。

発表概要

2024.flutterkaigi.jp

発表資料

speakerdeck.com


マッチングアプリ『Omiai 』のFlutterへのリプレイスの挑戦

Omiaiからは長年iOS, Androidそれぞれのプラットフォーム言語で開発されてきたアプリを技術的負債や仕様差異を解消するためにflutter化により解消していくお話しでした。リプレイス中にも既存アプリの機能追加は止めたくないということでAdd-to-Appによるアプローチをとっていたのは、弊社でも同様の経験があり当時のことを思い出させてくれるようでした。

リプレイスするにあたりマンパワーに依存することにより発生するコード規約違反や技術的負債の発生に対する対策として

  • 依存関係を明確にするためマルチパッケージ構成をとる
  • ユニットテストを十分に継続的に書く
  • 実装内容をパターン化し新規参入者に対する学習難易度を下げる

といったことを徹底されているようでした。

依存関係が明確にされていることで、依存に関する誤った実装がそもそもできないというように仕組みで解決されていたので素晴らしいと思いました。また各レイヤーでの責務が明確化されておりユニットテストを書くのも容易になったということも学ぶことができました。

コードへのドキュメーションコメントを書くのも必須にしており、そのチェックにpublic_member_api_docsというlintルールを活用していました。コメントを必須にすることによってソースコードが「実行可能な仕様書」にしているというのが興味深かったです。

またVS Codeのスニペット機能をかなり活用していたのも興味深かったです。 これを機に弊社でもスニペット機能は活用していこうと考えております。

発表概要

2024.flutterkaigi.jp

発表資料

www.slideshare.net


アニメーションを最深まで理解してパフォーマンスを向上させる

弊社のプロダクトでも各所にアニメーションを使っていますが、flutterでのアニメーションは若干特殊なところもあり、正しい実装なのか、他の代替実装やライブラリはあるのか、改善できる要素はあるのかなど、知見を増やすことを目的に本セッションに参加しました。

本セッションでは、flutterにおけるアニメーションの最新動向や入門解説、アニメーションの詳細な説明まで幅広く解説した、本セッションでflutterのアニメーションに関する知識を網羅的に学べる内容でした。

特にパフォーマンスの計測と分析のセクションでは、1000個のロゴを回転させたアプリを例に、パフォーマンス低下の原因とdevtoolsを使った改善方法の解説はとてもわかりやすく学びが多かったセッションでした。

発表概要

2024.flutterkaigi.jp

発表資料

speakerdeck.com


実践的パッケージ戦略

弊社でも、既存プロダクトのマルチパッケージ化を検討しており、ぜひ知見を得たいと思い、本セッションに参加しました。

本セッションではクリーンアーキテクチャを例に、riverpodを使った簡単なコードで説明するセッションでした。

まず3つのレイヤーを使ったシンプルなプロジェクトを例に解説していました。

次に上記の実装を依存性逆転の原則(DIP)に従い、以下のように依存関係を変更した実装の手順を説明をいただきました。

依存関係を逆転すると、当然直接モジュールを参照していたところは壊れるため、

下位になったUseCaseは依存してたモジュールを使用する際に、インターフェースを追加してそれを介して呼ぶように修正します。

上記になったGatewayは、UseCaseのUserRepositoryの具象クラスを実装して、それを返すproviderを更新します。

最後に、AppのProviderScopeのoverridesに更新したproviderを設定して完成です。

しかし、依存してるモジュールの数が増えていくと、都度overridesに追加設定していく必要がでてくる問題が発生します。

そこで、Kyoheiさん自身が作成した override_pod というツールを使うことで、build_runnerで自動生成して、前述の問題を解決できるようです。

今回のようにレイヤーごとにパッケージに分けて、マルチパッケージな構成するにあたり、melosというツールの紹介がありました。melos をつかったマルチパッケージプロジェクトでそのままtestを実行すると、期待した正しいカバレッジが得られないことがあるため、Kyoheiさん自身が作成したlcov_excluderというツールを使って除外設定することで、melosと併せて使うと便利とのことでした。

普段業務で、依存関係をひっくり返すようなことはする機会がなかったですが、実際今回の発表を例にriverpodでの解決方法は非常に興味深く学びの多かったセッションでした。

発表概要

2024.flutterkaigi.jp

発表資料

speakerdeck.com


Shorebirdを活用したFlutterアプリの即時アップデート:Code Pushの実践と可能性

Shorebird のCode Pushとは、Flutterをforkしたプロダクトで、Google Play StoreやAppStoreのアプリ審査フェーズをスキップして、Flutter アプリの変更差分をユーザに反映することができる夢のようなツール(サービス)です。

アプリリリースするまでに、必ず審査を通過しなくてはいけませんが、その審査結果はまちまちで、早くても半日〜1日かかってしまって、早くユーザに届けたいプロダクト側はいつももどかしい思いをした経験はあるのではないでしょうか?

その問題をこのShorebirdのCode Pushを使えば解消できる!?というものでした。

ただし、当サービスを利用するにあたって若干制約があるようでした

  • flutter v3.24.0以上の環境が必要(意外と高い)
  • 本家flutterでビルドしたアプリは不可
  • dartコードの差分のみ適用可能(assetの追加削除やネイティブコードの差分が含まれる場合は通常通りの各ストアのリリースフロー)
  • 各ストアのガイドラインには準拠(当然)
  • ユーザ側はアプリを2回起動が必要

料金プランは、従量課金制で5,000パッチ(1端末1パッチ計算)までは無料プランで使用可能なので、まず気軽に使い始めてもよさそうですね!

発表概要

2024.flutterkaigi.jp


Flutterアプリで可用性を向上させたFeatureFlagの運用戦略とその方法

トランクベース開発を実現するための仕組みであるFeature Flag に関するセッションで、実際にプロダクトで直面した課題と、それを踏まえた実装方法や運用について解説されていました。

弊社でもFeatureFlagを導入しており、発表前からとても注目していたセッションの1つでした。

FeatureFlagは新機能の公開/非公開をリリース後でも簡単に切り替えができる仕組みで、これにより、以下のようなメリットが得られます。

  • 開発中の機能をマージすることができる
  • PRの粒度を小さくできる (コンフリクトを抑える、レビューコストの軽減)
  • リリース後に大きな問題が起きてもすぐにロールバックできる (Firebase RemoteConfigなどとの連携)
  • ABテストの実施が容易になる

発表の中で特に印象的だったのは、UI層でのFeatureFlagの扱い方で、FeatureFlagをラップしたFlagBuilderというWidgetを用いているという点です。

FlagBuilder は、onBuilder と offBuilder という2つのコールバックを持ち、引数に渡した FeatureFlag の値に応じて、それぞれのコールバックが呼ばれる仕組みになっているようです。

if 文や三項演算子を使って条件分岐を行うと、分岐が散らばったり、可読性が低下することがありますが、FlagBuilder 内に分岐を集約することで、この問題を解消できている点が非常に良いと感じました。

また、既存の実装に関しては、コピペで offBuilder に残す運用を採用することで、デグレの発生を抑える取り組みが行われているとのことでした。

ロジック面においても、Feature Flag による制御を基本的に domain レイヤー(UseCase) のみに制限することで、条件分岐が分散しないようになっているようです。

Danger を使ってレビュー時に機械的にFeature Flag の制御を忘れに気づけるようにしている点も非常に参考になりました。

発表概要

2024.flutterkaigi.jp

発表資料

speakerdeck.com


DevTools Extensions で独自の DevTool を開発する

DevTools Extensions を使って独自のデバッグツールを作成する方法について、ライブコーディングを交えてとても詳しく解説されているセッションでした。

(NeoVimを使いこなしていてめちゃくちゃかっこよかったです 笑)

まず、 DevToolsに独自の機能を追加できることを知らなかったので、その点に驚きました。

セッションでは、DevTools Extensions を活用した具体的なツールとして、以下の3つが紹介されていました。

  • GraphQL Cache Inspector
    • GraphQLClientのキャッシュを可視化
    • 正規化されたTree構造で出力
  • Loading State Toggle
    • Loading状態のUIへの切り替え
    • Skeleton などのデザイン確認に使用
  • Dio Logger Toggle
    • Http通信のログ出力を ON/OFF
    • ログの追跡を容易にする

dev toolの作り方は下記の3ステップで比較的簡単に作成できるようです。

  • config.yamlの作成
  • Devtools extensionsのパッケージを作成
  • Flutter webでbuild

GraphQL Cache InspectorはReactのツールを参考に作成したとのことで、

どんなツールを作成するかのアイディアはWeb界隈のツールを参考にするのもオススメとのことでした。

DevTools Extensions を活用することで、アプリ内にデバッグ機能を埋め込むことなく、開発中のデバッグや日々の開発がより快適に行えるのは非常に嬉しいポイントですね!

発表概要

2024.flutterkaigi.jp

発表資料

speakerdeck.com


Effective Form ~ Flutterによる複雑なフォーム開発の実践 ~

ユーザーからの入力を受け取るためのインターフェースであるフォームの実装方法や注意点について詳しく解説されたセッションでした。

まず、例として挙げられたのはログインフォームです。

このフォームでは、EmailとPasswordを入力値として受け取り、Loginボタンが表示される比較的シンプルな画面が想定されています。

フォームのフローは以下の通りです。

  1. UIの表示
  2. 入力状態の管理
  3. バリデーション
  4. Dirty管理
  5. Submit

特に注目したいのが、4番目のDirty管理です。

EmailのTextFieldにシンプルなバリデーションを適用した場合、初期状態でいきなりInvalid状態になってしまうという問題が紹介されました。

Dirty管理は、こうしたケースでバリデーション結果をユーザーにフィードバックするタイミングを適切に制御するための考え方とのことです。

Dirty管理のポイント

  • 入力フィールドが変更されたタイミングを追跡
  • ユーザーが変更を確定したタイミングで「dirty状態」と見なす
  • エラー表示や変更確認ダイアログの表示タイミングを管理できる

このDirty管理を実現する方法として、formzというパッケージが紹介されました。

formzパッケージには、FormzInputという抽象クラスが用意されており、入力値を「pure」と「dirty」の2つの状態で管理できるようです。

TextFieldのonChangedでpure状態に、onSubmittedでdirty状態に切り替えることで、Dirty管理を実現できます。

また、validatorメソッドをオーバーライドすることで、バリデーションロジックを実装できます。

displayErrorの値を使うことで、dirty状態の場合のみエラーを表示することができ、エラー表示のタイミングを柔軟に制御できる点が非常に便利ですね!

さらに、より複雑なフォームにおける実装課題とその戦略についても解説がありました。

  • 管理すべき状態が多い → Single Source of Truthの担保 (状態の一貫性が担保できる)
  • 状態更新による多彩な動的制御が必要 (状態が決まれば挙動が決まる)
  • 大量の機能と複雑な依存 (状態の管理範囲が最小化される)

弊社のアプリでも複数の場所でフォームを使用しているため、Dirty管理や設計戦略を踏まえて改善に活かしていきたいと思います。

発表概要

2024.flutterkaigi.jp

発表資料

speakerdeck.com

最後に

冒頭でも触れましたが、今年は2日間にわたる開催で、内容が非常に充実していました。 どのセッションもとても多くの学びがあり、参加者の皆様の熱意にも多くの刺激をいただきました。 登壇者の皆様、そして運営スタッフの皆様、本当にありがとうございました。 来年のFlutterKaigiも楽しみにしています。

YYCのバックエンドをPerl5.40とDebian Bookwormへ更新したプロジェクトを振り返る

こんにちは Diverse developer blogです。今回はプロジェクトの構想から完了まで、1年半ほどかけて行った「PerlとDebianの更新プロジェクト」を振り返ります。

なぜやったのか?

弊社のYYCは20年以上稼働しているサービス(SNS, マッチング, ライブ配信)です。ユーザーの要望に応えるため、機能開発を優先してきたことで開発環境の改善が遅れていました。

特にバックエンドの開発言語(Perl 5.8)と、コンテナOS(CentOS)のアップデートが遅れており、今後の機能開発やセキュリティ対応に課題が生じていました。

そのため、プロジェクトの目標は「開発言語とコンテナOSをLTS(long-term support)バージョンまで更新する」ことにしました。そして、課題を一つ一つ段階的に解決して、ついに目標を達成しました。現在のYYCのバックエンドは、最新のPerl5.40とDebian Bookwormで稼働しています。

どうやったのか?

ここらはプロジェクトの進行を時系列順に紹介します。

1. 段階的リプレイスで失敗した

プロジェクト当初は、当時のYYCとは別にYYC v2を開発して画面や機能ベースで段階的にリプレイスする方式をとりました。しかし、新旧のYYCから共通のDBを安全に操作するのが難しくなり、途中でリプレイスを中止しました。

当時の判断や取り組みは、YAPC::Kyoto 2023で登壇した資料 にまとまっています。この取り組みは失敗になり、段階的なリプレイスに半年ほど費やしました。しかし、サンクコストを気にせずに方針を転換して、今では正しかったと思います。

2. リファクタリングに方針転換した

段階的なリプレイスで開発したコードやリソースは完全に削除して、既存のYYCをリファクタリングする方針に切り替えました。まずは、開発環境を理想の状態に近づけることを目指しました。そして、この作業で出た差分を本番環境へ徐々に適応しました。実施した順に具体的な作業内容を箇条書きで紹介します。

  1. CentOSをDebian Busterへ移行する
    • 開発環境のコンテナOSをまずはDebianベースへ移行した
  2. mod_perl v1をStarmanとPSGI(Perl Web Server Gateway Interface)へ移行する
    • PSGIでも動作するか開発環境で検証した
    • Perlのバージョンを固定している原因のひとつがmod_perl v1だったため、mod_perlは置き換え可能か調査した
  3. Perlは5.16までアップデートする
    • 5.18にアップデートするとコードの修正箇所が多いため
      • 例えば foreach my $hoge qw(a b c) {} が使えない
      • 多数のモジュールがインストールに失敗する
    • 5.16でモジュールの整理整頓と非推奨の警告修正を優先した
  4. ファイルベースで管理していたライブラリをcpanfile経由へ移行する
    • プロジェクトで使用中のライブラリを洗い出し、必要なライブラリのみを移行した
    • すべてのパッケージを最新バージョンにアップグレードした
    • 移行できないライブラリ(社内専用、CPANに存在しない)は、専用ディレクトリを用意してコードをそのままコミットして利用する方式をとった

3. 段階的にLTSバージョンまでアップデートする

PerlもDebianも段階的にアップデートしました。まずは、Debian Busterで本番環境でも正常に稼働する確認がとれてから、Perlのアップデートへ移りました。段階的な手順は以下のとおりです。

  1. Perl5.8 + mod_perl + busterとPerl5.16 + PSGI + Starman + busterのどちらでもバックエンドが起動して単体テストとE2Eテストが通ることを確認した
  2. パフォーマンステスト(taurus)で性能劣化がないことを確認した
  3. Perl5.16 + PSGI + Starman + busterをリリースして正常に稼働した

最後にPerl5.38.2をアップデート対象にしてコードの修正をしつつ、2024年6月30日にBusterはEOLをむかえるため、Bookwormの検証も同時に開始しました。ところが、この作業中にPerl5.40がリリースされました。Perl5.38.2で動作確認がとれていたのでPerl5.40へアップデートしてリリースしました。Perl5.40 + PSGI + Starman + bookwormでリリース後、use v5.40; をすべてのPerlのコードに追記して、プロジェクトは完了しました。

4. アップデート対応で工夫したこと

このプロジェクトと同時並行で、現行環境での機能開発も継続して行っていました。そのため、Perl 5.16 + PSGIへの移行時は、新しい環境の変更をできるだけ現行環境にも取り込んでいく必要がありました。特に以下の2点を重視していました。

  • 新しい環境の変更点を現行環境の開発中でも意識できるようにして移行をスムーズに進めたい
  • コード自体は事前にリリースしておき、環境の切り替えはコンテナイメージの変更のみで行い、切り戻しをしやすい状態にしたい

これらを実現するために以下の工夫をしました。

  • Perl5.8 + mod_perl と、Perl5.16 + PSGI どちらでもプロジェクトのコードが動くように、ベースクラスで環境の違いを吸収した
  • Apache::ConstantsApache::Singletonなど環境に依存するパッケージを直接使っている場合は、プロジェクト内に同様の役割のクラスを作成して事前に移行した
  • パッケージの最新化で Perl5.8 環境から挙動やインタフェースが変わる場合には、一時的にプロジェクト内で該当のパッケージを継承したり MixIn をすることで、Perl 5.16 環境と同じように動くようにした
  • CI では Perl 5.8 + mod_perl と Perl 5.16 + PSGI の2つの環境を用意し、どちらの環境でも動作確認できるようにした

2つの環境をまたがって作業すると、混乱することはありました。しかし、切替はイメージの変更だけで行えたので、不具合の特定やロールバックはしやすい状態で移行できました。正常に移行できた後、新旧の両方で動くように工夫したコードはすべて削除しました。

やってよかったことは?

1. 課題と解決策がわかりやすくなった

アップデートを安全かつ効率的に進めるために不要なコードや機能をたくさん削除しました。考慮するコンテナの数やライブラリの数も減りました。開発言語とOSのアップデートと同時に、利用中のミドルウェアやライブラリも最新化できました。この結果、問題の特定が楽になり、新たな課題の発見とその解決策がわかりやすくなりました。

2. 取れる選択肢が増えた

開発言語もOSもLTSバージョンなので、ライブラリやパッケージが利用できないケースが減りました。以前まではOSが古いため、PerlだけでなくNode.jsなどの他のライブラリのバージョンも更新できない状況でしたが、その心配はなくなりました。

まとめ

プロジェクトを完了して、古く閉ざされた開発環境から解放されました。開発するモチベーションも上がっています。このようなプロジェクトを経験できたのは、多くのユーザーがYYCを長年利用してくれた結果だと思います。今後は、もっと早く計画的に対応できるよう、Diverseでは継続的な改善を怠らない体制を維持していきます。

ブログの内容や弊社に興味のある方は、ぜひ以下の採用ページからカジュアル面談へ!様々な意見をお待ちしています。

diverse-inc.co.jp

メール配信基盤をSendGridへ移行している話

こんにちは、Diverse developer blogです。最近弊社では、メール配信基盤の移行作業を行いました。今回はその経緯についてご紹介いたします。

背景

弊社では、複数のメール配信サービスを利用しており、AWS EC2上に構築したメールサーバーで運用していました。しかし、複数のサービスを利用することでメールの管理が煩雑になっていました。

SendGridの選定理由

SendGridに移行した主な理由はコスト削減で、具体的には月額約10万円のコストが削減されます。一方、新しいメールサービスへの移行によるコストは増加しますが、これはメンテナンスと管理の効率化によって相殺されると見込んでいます。 加えて、SendGridはサーバーレスであり、メール送信プロセスをAPIで統一できるため、AWS EC2のメールサーバー管理コストも削減されます。

sendgrid.kke.co.jp

移行手順

移行した手順と、進める際に留意したポイントについて以下でご紹介します。

1. 送信量とプランの適正確認

SendGridは、プランによって送信可能なメールの量が異なります。移行の検討段階で、現在の送信量とSendGridのプランを比較し、適切なプランを選択できるよう概算を立てました。

2. 独自ドメインの設定と認証

SendGrid上のドメイン設定(Domain Authentication)で、SPFやDKIM、DMARCに必要なDNSレコードをSendGridが自動的に生成します。それを弊社が管理するAmazon Route53へ登録します。 手順詳細については、マニュアルが用意されているので、それに従ってスムーズに進めることができました。

独自ドメインを利用する - ドキュメント | SendGrid

3. APIの実装とテスト

既存のメールサービスの使用範囲を調査し、影響範囲が最小のサービスから開発環境でSendGridへの移行作業を開始しました。SendGridの公式ライブラリではサポート外のPerlで開発しているため、REST APIへ直接リクエストする形で実装しました。事前の調査で既存システムへ置き換えられるSendGridのAPIを検討していたため、スムーズに実装自体は進めることができました。

移行作業中に苦戦したこと

移行作業中、メール送信処理後にSendGrid側で受付完了したメールが宛先に届かない問題が発生しました。調査を行いましたが解決に至らず、問い合わせて判明した原因は、SendGridのアカウントが無効化されていたことでした。SendGridの管理画面上で警告があったのを見落としていたようで、しばらく使用していないアカウントだったのが原因というオチでした。 問い合わせ後、回答が24時間以内で迅速に届いたので、今後トラブルが発生した際も迅速に対応してもらえそうです。

開発環境での実装に問題がないことを確認できた後は、SendGridを無料プランから有料プランへ切り替え、本番環境へリリースしました。

最後に

まだ移行できたサービスは一部ではありますが、この変更によりメール配信システムの効率化を図ると共に、コスト削減も達成できました。残っているサービスも順次移行作業を進めていく予定です。今後も、システムの改善に向けた取り組みを続けていきます。

Diverseエンジニアチームの2023年の開発を数字で振り返る

こんにちは。 Diverse developer blogです。今回は2023年のDiverseエンジニアチームの開発を数字で振り返った話をします。年間振り返りMTGにはエンジニア全員が参加して、CTOが数字をもとに年間を振り返ったあと、Miroを使ってCTO以外のエンジニアも2023年の開発を振り返りました。

利用した数字

振り返りMTGで利用したデータは以下の4つです。

  1. 開発生産性の指標(Git)
  2. スプリントタスクの完了タスクの数(Asana)
  3. リリースした施策の数(Notion)
  4. インシデント報告書の数(Notion)

開発生産性はGitのコミットログを使って「デプロイ頻度」や「変更障害率」を計測しています。詳しくは Diverseが開発生産性を計測する理由 - Diverse developer blog をご覧ください。

弊社はスクラムで開発しており、1スプリント1週間です。このスプリント期間だと、モバイルアプリの場合、年間リリース数は月が約4週なので約48回になります。計測すると、2023年はちょうど48回でした。一方、モバイル以外のWebフロントエンドとバックエンドはモノリポで開発しており、1日平均で約3.7回デプロイしており、エンジニア1人あたり1日に約1.6回Pull Requestを作成してmainブランチへマージしています。

単純に量のみで生産性を振り返ると、スプリントのサイクルは回っているように見えます。エンジニアからは、スプリントタスクをこなす量が昨年よりも増えた(たくさん開発や施策をこなせた)という声が出ました。

このようなエンジニアの声は、Miroを使って可視化しています。弊社の振り返りはKPTに加えて、GoodとActionを加えたGKPTAで振り返るフレームワークを採用しています*1。GoodはKeepから継続を抜いて素直に良かった出来事を書きます。ActionはTryに繋がる具体的で小さい行動を書きます。

GoodとActionを加えたのは、出来事と感情(例:◯◯が嬉しい、イラっとした、ツラかった、楽しかった)を一緒にして書きやすい枠をつくり、付箋を貼るハードルを下げたいのと、抽象的な内容になりがちなTryを具体的な行動で考える方向にシフトさせたいからです。*2

来年に向けたチャレンジ

ここまで数字のみで主に生産性を振り返りましたが、生産効率の観点でみると課題はあります。

プロダクトの施策を設計する弊社のBizチームは、施策の内容と結果をNotionに書いています。今年の施策ページ数は、38件で月に3件ほどのペースです。1スプリント1週間だと、ユーザに対してインパクトのある施策をまだ1件届ける余地がありそうです。そして、一部の施策は期待した成果にならなかったものもあります。

小出しで小さく検証するサイクルを回して、不確実性の高い市場に価値を届けるのを理想とするならば、施策の設計や実装には改善の余地がまだまだあります。

さらに、Asanaで集計した年間の完了タスク数のうち、不具合の修正タスクが約35%でした。またインシデント報告書もインシデントのレベルの高低差はありますが、年間通して数件発生しました。生産性のために効率を犠牲にしては本末転倒です。来年はこれらの数値を適切に下げて、検証のサイクルをチーム全体で回せるようにチャレンジしていきます。

まとめ

これらの数字の正確な計測は、今年から開始しました。したがって、現時点では過去と比較してどれだけ改善できたのか、また出来なかったのかわかりません。来年も引き続き計測して、自分たちの開発を感覚による感想ではなく、具体的な数字と共にどう改善できるか振り返られる状態にしていきます。

このようなチーム開発に興味のある方は、ぜひ以下の採用ページからカジュアル面談へ!様々な意見をお待ちしています。

diverse-inc.co.jp

*1:ふりかえりガイドを変更しました(第36版) - https://www.agile-studio.jp/post/update-retrospective-guide-v36

*2:付箋は社外秘もあるので一部モザイクにしています

FlutterKaigi 2023に参加してきました

はじめに

2023年11月10日(金)に開催されたFlutterのカンファレンス、FlutterKaigi2023 に参加してきましたので、その感想を綴ろうと思います。

イベント概要

FlutterKaigiは、日本において開催されるFlutter技術情報の共有とコミュニケーションを目的としたカンファレンスです。

行動規範 | flutterkaigi

flutterkaigi.jp

WebサイトもアプリもFlutter製!

FlutterKaigiは今年で3回目でオフライン開催は今年が初!

会場は、表参道のナビタイムジャパン社の1Fフロアをセッションブース2つとスポンサーブースに分かれて使用。

時間は、10:00~18:20 +after party(懇親会)のスケジュールで行われました。

印象に残ったセッション

基調講演

Googleの方による、2015年から今にいたるまでのFlutterの歴史を振り返る内容でした。

弊社はFlutter v1 がリリースされる前である2018年からFlutter開発に着手し初めていたので、発表を聞きながら回想に浸っていました。

リリースから現在に至るまで安定性とパフォーマンスアップに注力し、ドキュメントも充実しており、いい意味で枯れた技術となった現在新規プロジェクトでFlutterを採用することに躊躇する必要はないと確信しました。 またWeb〜Linux・3Dゲームに至るまでカバーしていくとのことでますます今後のFlutterの成長が楽しみになりました。

また発表中に状態管理の話題もでて、Googleの方もriverpodを使っているとのことでした。

Flutterアプリにおけるテスト戦略の見直しと自動テストの導入

発表者のチームにe2e自動テスト導入までの背景と導入時のツール選定、どこまで網羅するかの線引きの話など事例をまとめた、かなり密度が濃い発表。

Unit TestやVRTで自動テストやり尽くしたが、さらにQC効果をあげるためにe2eの導入を検討しているプロダクトを抱えてる方には大変参考になる発表でした。

Add Material touch ripples

NavitimeのKosuke MatsumuraさんによるMaterialデザインにおけるタッチエフェクトについての解説でした。 普段の開発において見落としがちなボタンへのタッチエフェクトについて、その大切さを改めて認識させてくれるスピーチでした。 個人的にはKosuke Matsumuraさんが角丸の範囲を超えてタッチエフェクトがついているボタンを見ると許せないとおっしゃっていたのが面白かったです。 基本のInkWellの他に、InkResponse, TableRowInkWell等知らなかったWidgetも紹介されていました。

Master of flutter lifecycle

まずスライドデザインがアプリ風でおしゃれだった発表。

Flutterによる基本的なlifecycleの紹介と、現状最新版であるFlutter v3.13.0とそれ以前で実装の差分について紹介する内容。

AppLifecycleListenerの登場によって、StatefulWidgetからlifecycleの実装が剥がせるようになるのは衝撃でした。

3.13.0で追加されたhiddenは主にweb用のためアプリでは気にしなくてよいというTipsも知見を得ることができました。

詳解!Flutterにおける課金実装

アプリからカレーを注文できるTOKYO MIX CURRYでの課金の実装について解説されていました。 TOKYO MIX CURRYでは購入できるのがカレーという実物のため、クレジットカードやバーコード決済、タッチ決済など多岐な決済手段を実装しています。 前半と後半に分かれており、前半では元々Swift製だったものがいかにしてFlutterに変わっていくのかのお話をされていました。 スピーカーの方が最初Flutterを採用するのは厳しいという意見だったのが、今にして思えば全然杞憂だったと言っていたのが印象的でした。

後半では実店舗での注文〜決済までできるアプリについての解説でした。 同時注文されたり、途中でキャンセルされたまま放置されることによって引き起こされるバグなどをお話しされており、アプリだけで閉じてるサービスでは想定できないバグが起きるのは興味深かったです。

今度TOKYO MIX CURRYで注文してみたいと思いました!

Dartのコード自動生成の仕組みとコード自動生成のパッケージを自作する方法について

Dartの自動生成におけるツールの紹介、コードでの実装方法の紹介を基本編、実践編の三段構成の発表。

基本編はサンプルのコードをコピーする内容だったが、数行書くだけで自動生成できるのは衝撃でした。

実践編は内容が濃く、スライドに加えてGitHubのコードを実際に触りながら学習するとよさそうな内容でした。

Flutterアプリのセキュリティ対策を考えてみる

debug/releaseビルドでの内部の仕組みの違いの紹介から、Flutterでの基本的なセキュリティ対策の紹介から便利なpluginの紹介までの発表。

リリースして満足しがちだけど、そのアプリ本当に大丈夫?と改めて考えさせられる内容で、

スライドがとても簡潔にまとめられていて、学びの多かった発表でした。

通信の中間者攻撃を防ぐためにSSLのfinger printをサーバー経由で受け渡してセットする方法が紹介されていましたがスピーチ終わりの質問でそのfinger printを受け渡しするAPIが攻撃を受けた場合にどうするのか?という質問もあり、セキュリティとは常にイタチごっこなんだなと改めて考えさせられました。

最終的にはサービスの提供者がセキュリティリスクをどこまで許容するのかしないのかの線引きをきっちりしてそれに合わせた対応をしていくことが重要なんだなと認識させられました。

魅せろ! Flutter で目を惹く UI デザインを実装する

Flutterでユーザーの目を惹くUIデザインの作り方をFlutterの奥深くにあるclass等のカスタマイズ方法や、riveによるUIデザインについて紹介されていました。 Flutter Puzzle Hackで自信を持って提出したゲームが入選せず、何かの間違いかなと思ったけど他のゲームを見てみるとすごいアニメーションで納得の結果だということをおっしゃっていて、特にゲームなどは業務アプリとは異なるレベルでUI,アニメーションに力を入れる必要があるのだと思いました。 実際に公開されているゲームもやってみましたが、私からみると十分すごかったです。

tomohiko-tanihata.github.io

個人的にはスピーチのテンポもよく、人を惹きつけるような話し方で聞いていて楽しかったです。

印象に残ったスポンサーブース

フロアは広々としてて、回りやすかったです。

弊社もシルバースポンサーで参加していました!

ノベルティでバズっていたm3社のステッカーがこちら。

Flutter開発してる人は一度は遭遇したことあるエラーをモチーフにしてて、アイデアが秀逸でした(笑)Flutter完全に理解したステッカーは完全には理解できてなかったようです。

また、ゆめみ様のブースでは、Dartのコードに関する問題が2問出題されていて、回答できたらノベルティをいただけるものでした。

Dart3のsyntaxに関するものや、riverpodに関する良問で興味深いものでした。

最後に

私個人としてはオフラインでのカンファレンス参加が久しぶりで、熱量高い参加者から刺激を受けました。

セッションも現状の他者事例や運用、開発体制などの知見が得られて身になるものばかりで、充実した時間を過ごすことができました。

来年の開催もぜひ楽しみにしています!ありがとうございました!

(写真は主宰であるkikuchyさん挨拶時の様子です)

AWS JumpStart 2023 運用編に参加しました

はじめに

こんにちは!今回は2023年10月18日に開催された「AWS JumpStart 2023 運用編」に参加してきたので、その体験レポートを残そうと思います。

参加経緯

私は普段、サーバーサイドとフロントエンドの開発に携わっています。 社内のプロダクトでAWSを使用しており、開発時のデバッグ環境構築やデプロイ、本番障害の調査などでAWSコンソールを操作する機会もあります。 AWSの知識としてはアーキテクチャ図を見て各AWSサービスの役割や基本的な概要は理解できる程度です。

弊社では「Fail Fast, Go Higher(大胆に試そう、そして成長しよう)」を行動指針のひとつとしています。

社内には専任のインフラエンジニアもいますが、AWSは開発に密接に関わるので自身でもより実践的な知識を習得したいと考えています。アプリケーションの効率的な運用とスムーズな開発を実現するために、パフォーマンスの最適化やモニタリングなど、どこに改善の余地があるかまたその実現方法としてどんなサービスがあるのか。視野を広げるヒントとなればと思い、今回の研修プログラムに参加しました。

イベント概要

「AWS JumpStart 2023 運用編」は AWS 初学者のエンジニアの方々を対象とした、実践的な研修プログラムです

将来的にAWS 活用をリードする人材になるための第一歩をスムーズに踏み出せるようなプログラムをご提供します 単なるAWS サービスの学習だけでなく、運用時に直面する具体的なユースケースや課題を例に適切な対応をご自身で検討・実施できるようになる部分にフォーカスした内容となっております

イベント当日には350人前後が参加されており、インフラエンジニア、サーバーサイド、フロントエンド、情シス、QAなどなど異なるポジションの方が集まっていました。 講義中は質問をslackに投稿していく形式で行われ、他の参加者の質問も見ることができます。自身とは異なる視点で新しい気づきにもなり、後日一通り眺めてみても面白かったです。

プログラムの内容

IaC編

講義では「Infrastructure as Code(IaC)」について学び、IaC関連のサービスである「AWS CloudFormation」と「AWS CDK」の構成、仕組み、開発フローについて解説を受けました。 ハンズオンでは「AWS Cloud9」を使いコードを書き、CDKでCloudFormationのテンプレート作成からデプロイまでの実際のプロセスを体験しました。

実施したハンズオンはこちらに公開されているので、ご興味がある方はぜひお試しください。

catalog.workshops.aws

CI/CD編

CI/CD編では必要性について学び、その実現のためのサービスのひとつとして「Amazon CodeCatalyst」が紹介されました。 ハンズオンではCodeCatalystを使用して、Issueの管理からプルリクエストの作成、デプロイまでのフローを体験しました。

実施したハンズオンはこちらに公開されているので、ご興味がある方はぜひお試しください。

catalog.workshops.aws

モニタリング編

モニタリング編ではObservability(可観測性)に焦点を当て、監視の目的について学びました。また、アンチパターンからベストプラクティスまでの実例の解説を聞けました。 ハンズオンでは「Amazon CloudWatch」を活用して、ELB、ECS、RDSのメトリクスを確認し、それをダッシュボード上に可視化できるようグラフを作成。さらに、「AWS CloudShell」を使用して、アプリに大量のリクエストを送り続ける負荷をかけ、数値やグラフの変化を観察できました。

最終的に作成したダッシュボードはこちらのようになりました。

参加してみて

ハンズオンで実際にコードを書いて印象的だったのは、CDKのコードが非常に簡潔である点です。少ない記述で、AWSのベストプラクティス設定内容がCloudFormationテンプレート生成時に自動的に反映されるため、非常に便利でした。 弊社ではTerraformを使用していますが、CDKとの利点と欠点について今後深掘りして比較してみたいなと思いました。

モニタリングでは業務上、CloudWatchを使用する機会は以前からありましたが、ダッシュボードなどは主に既存の完成したものを参照する程度にとどまっていました。ですが今回の研修プログラムを通じて、具体的なメトリクスの解釈方法やグラフの作成方法など、詳細な可視化手法を学ぶことができ、非常に有意義でした。

今回学んだ内容を起点として、さらに気になった内容を深掘りして学んでいきたいと思います。

Aurora MySQL version2 から version3にアップグレードした話

こんにちは、Diverse Developer Blogです。

今回は、2024年10月31日でEOLを迎えるAurora MySQL v2からAurora MySQL v3のアップグレードの話をします。 Blue/Green deploymentを利用してアップグレードを行ったので、その前提での内容となります。

Blue/Green deploymentを利用することで発生した問題

Blue/Green作成時に「mysql.flush_rewrite_rules」のエラーが発生する

Blue/Greenの作成ボタンを押した段階で、エラーが発生しprecheckログには「mysql.flush_rewrite_rules」に関するエラー内容がありました。

        {
            "id": "routinesSyntaxCheck",
            "title": "MySQL 8.0 syntax check for routine-like objects",
            "status": "OK",
            "description": "The following objects did not pass a syntax check with the latest MySQL 8.0 grammar. A common reason is that they reference names that conflict with new reserved keywords. You must update these routine definitions and `quote` any such references before upgrading.",
            "documentationLink": "https://dev.mysql.com/doc/refman/en/keywords.html",
            "detectedProblems": [
                {
                    "level": "Error",
                    "dbObject": "mysql.flush_rewrite_rules",
                    "description": "at line 5,8: unexpected token 'QUERY'"
                }
            ]
        },

解決策

AWSに連絡してプロシージャをDROPしてもらうことで解決しました。

本問題は RDS for MySQL DB インスタンスから移行した DB クラスターにおいて発生する場合があることを確認しております

ということで、RDS for MySQLからAuroraに移行したデータベースでは発生することがあるそうです。

Blue/Green切替ができない

Blue環境とGreen環境の切り替えが失敗してしまう

Message : Switchover from DB cluster dev-aurora to dev-aurora-green was canceled due to external replication on dev-aurora. 
Stop replication from an external database to dev-aurora before you switch over.

解決策

元々オンプレミスからRDSに移行した際に、ライターインスタンスのSlave解除をせずに運用していたため発生していました。 ライターインスタンスのリセットを行うことで解決しました。

SELECT * FROM mysql.rds_history;

もしリセットされてなかったら

CALL mysql.rds_reset_external_master;

でリセットする

MySQL5.7 → MySQL8.0 になったことによる問題

Rankが予約語になった

選択肢として、

  1. アプリケーション側でのエスケープ対応

  2. カラム名の変更

となると思いますが、エスケープ忘れなどミスが起きる可能性があるため 2. カラム名の変更 で対応しました。

移行後に特定クエリのパフォーマンスが劣化した

巨大なテーブルをJOINするクエリにおいてパフォーマンスが劣化してしまう

解決策

MySQL8.0から一時テーブルの動作が変更されていたことが原因でした。

公式ドキュメントには

一時テーブルの累積サイズが 20 GiB になることがわかっています。インメモリ一時テーブルを 2 GiB に設定し、ディスク上で最大 20 GiB に拡張します。 temptable_max_ram を 2,147,483,648 に、temptable_max_mmap を 21,474,836,480 に設定します。これらの値はバイト単位です。 これらのパラメータ設定により、一時テーブルが累積合計 22 GiB に拡張できます。

と記載がありましたが、JOINするテーブルサイズから半分程度の値でストレージエンジンパラメータ(temptable_max_ram、temptable_max_mmap)を調整する対応を行いました。 この対応によりパフォーマンスがAurora MySQL version2と同等のパフォーマンスに改善しました。

まとめ

MySQL8.0に上げて良かったこと

  • MySQL 8系統にアップグレードしたことで、以前は使用できなかったWith句など、利用したかった機能が利用可能になり分析チームの効率が上がりました。

Blue/Green deploymentを利用して良かったこと

  • 大変なDBのアップグレード作業をコンソール上の簡単な操作で実行できました。
  • 開発環境での検証中でエラー時にも正常に元の状態にリバートすることを確認できていたので、本番でも安心して作業を進めることができました。

AWS公式の記事以外で参考にした記事